Modifying localStorage gives A cross-origin error - javascript

I'm making a web application using reactjs, and when development is suddenly this error appears:"A cross-origin error was thrown. React doesn't have access to the actual error object in development".I AuthContext witch gives user data to localStorage :
const AuthProvider = ({ children }) => {
const token = localStorage.getItem("token");
const userInfo = localStorage.getItem("userInfo");
const expiresAt = localStorage.getItem("expiresAt");
const [authState, setAuthState] = useState({
token,
expiresAt,
userInfo: userInfo ? JSON.parse(userInfo) : {},
});
const setAuthInfo = ({ token, userInfo, expiresAt }) => {
localStorage.setItem("token", token);
localStorage.setItem("userInfo", JSON.stringify(userInfo));
localStorage.setItem("expiresAt", expiresAt);
setAuthState({
token,
userInfo,
expiresAt,
});
};
Unfortunately i have a problem with updating user details.
In context i made another function:
Edit: I forgot to write that after the function is executed userDetails changes to undefined so I get a cross-origin error
const setUserInfo = ({ userInfo }) => {
localStorage.removeItem("userInfo");
localStorage.setItem("userInfo", JSON.stringify(userInfo));
setAuthState({
userInfo,
});
};
I have rest-api route to update-details , exemplary response:
{
"success": true,
"user": {
"role": role,
"_id": id,
"username": name,
"email": email,
"createdAd": createdAt,
"__v": 0
}
}
And user rest-api response when user login, example:
{
"success": true,
"token": token,
"expiresAt": expiresAt,
"userInfo": {
"role": role,
"_id": id,
"username": name,
"email": email,
"_id": id
}
}
Updating details working when i call it but after i get cross site error.
And heres Submit function
const handleUpdate = async (info) => {
setError("");
setLoading(true);
try {
const { data } = await fetchContext.authAxios.put(
"http://localhost:5000/api/v1/auth/update-details",
info
);
const user = data.user;
console.log(user);
auth.setUserState(data);
setError(null);
setLoading(false);
} catch (err) {
setLoading(false);
// const { data } = err.response;
// setError(data.error);
console.log(err);
}
};

Ok i dumb
const setUserInfo = ({ userInfo }) => {};
should be
const setUserInfo = ( userInfo ) => {};

Related

"Error: Error serializing .customerId returned from getServerSideProps in "/pricing"

I keep trying to call an api from my getServerSideProps function in my Next.js application, but everytime I try to do so I get this error
"Error: Error serializing .customerId returned from getServerSideProps in "/pricing".
Reason: undefined cannot be serialized as JSON. Please use null or omit this value."
This is the code for the Pricing page
const Pricing = ({customerId}) => {
console.log(customerId, 'Customerid Pricing')
return(
<div>
<ProductDisplay customerId={customerId}/>
</div>
)
}
export const getServerSideProps = async (ctx) => {
//create customer variable
let customerId
// Create authenticated Supabase Client
const supabase = createServerSupabaseClient(ctx)
// get the user session from supabase
const { data: { session }, } = await supabase.auth.getSession()
//get the user email from the session
const email = session.user.email
//create stripe customer
const createCustomer = async () => {
let createdCustomer;
let customerAvailable;
try {
const checkCustomer = await stripe.customers.search({
query: `email: '${email}'`
})
createdCustomer = JSON.parse(JSON.stringify(checkCustomer))
customerAvailable = createdCustomer.data
} catch (error) {
console.log(error)
}
if (customerAvailable.length) {
customerId = createdCustomer.data[0].id
} else {
try {
const res = await fetch('/api/create-customer', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email
})
})
const newCustomer = await res.json();
customerId = newCustomer.customer.id
} catch (error) {
console.log(error)
}
}
}
if (session) {
createCustomer()
} else {
return{
redirect: {
destination: '/signin',
permanent: false,
}
}
}
return {
props: {
customerId
},
}
}
export default Pricing;
This is the /api/create-customer the fetch function is trying to call
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY)
const handler = async (req, res) => {
const {email} = req.body
try {
const customer = await stripe.customers.create({
email: email
});
res.status(200).json({
code: 'customer_created',
customer,
})
} catch (error) {
console.log(error);
res.status(400).json({
code: 'customer_creation_failed',
error: error
})
}
};
export default handler;
please help me, thank you very much.

Getting following error while fetching data in react Uncaught (in promise) TypeError: Failed to fetch

I have create backend using express and mongodb database. I am trying to fetch data in react but getting an error while fetching the data as show. Please can anyone tell what the solution of above error is and how can i fetch data from the backend
const Register = () => {
const [values, setValues] = useState({
name: "",
age: "",
country: "",
email: "",
});
const setData = (e) => {
console.log(e.target.value);
const { name, value } = e.target;
setValues((val) => {
return {
...val,
[name]: value,
};
});
};
const addData = async (e) => {
e.preventDefault();
const { name, age, country, email } = values;
const res = await fetch("/register", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name,
age,
country,
email,
}),
});
const data = await res.json();
console.log(data);
if (res.status === 404 || !data) {
console.log("Error");
} else {
console.log("Data added successfully");
}
};
Here below is the backend code where the post function is performed.
router.post("/register", async (req, res) => {
const { name, age, country, email } = req.body;
if (!name || !age || !country || !email) {
res.status(404).send("Some data is missing");
}
try {
const preuser = await Crud.findOne({ email: email });
console.log(preuser);
if (preuser) {
res.status(404).send("The user already exists");
} else {
let addUser = new Crud({
name,
age,
country,
email,
});
addUser = await addUser.save();
res.status(201).json(addUser);
console.log(addUser);
}
} catch (error) {
res.status(404).send(error);
}
});
await fetch leads to an exception when the HTTP status is ≥ 400. You must add a try-catch block to handle such exceptions:
try {
const res = await fetch("/register", {...});
} catch(exception) {
// Handle the exception
}
Also, HTTP status 404 should be used when a resource is not found. You use it when a user already exists (where status 400 would be more appropriate) or in case of a database error (when 500 would be more appropriate).

Using Google Oauth in FeathersJs with an existing access token

How do I use the Google Oauth in featherjs with an existing access token? The docs do not give an example on this. The only example is through the browser as shown here.
When going through the browser, http://localhost:3030/oauth/google works ok. I can successfully add the user to my DB. Here is my code:
const { LocalStrategy } = require("#feathersjs/authentication-local");
const { expressOauth } = require("#feathersjs/authentication-oauth");
const { OAuthStrategy } = require("#feathersjs/authentication-oauth");
var uniqid = require("uniqid");
const { AuthenticationService, JWTStrategy } = require('#feathersjs/authentication');
class GoogleStrategy extends OAuthStrategy {
async getEntityData(profile) {
const baseData = await super.getEntityData(profile);
console.log({ profile });
return {
...baseData,
profilePicture: profile.picture,
email: profile.email,
password: uniqid.time(),
};
}
}
module.exports = (app) => {
const authentication = new AuthenticationService(app);
authentication.register("local", new LocalStrategy());
authentication.register('jwt', new JWTStrategy());
authentication.register("google", new GoogleStrategy());
app.use("/authentication", authentication);
app.configure(expressOauth());
};
However if I try using an access token,like so
POST http://localhost:3030/authentication
data: {
"strategy": "google",
"accessToken": "ya29.A0ARrdaM_UJa6idfZr-4taqwkJ6qGBV1Dp9wbxF-wsult8dNPaVNCVg6Fndmrqv7BhRSwxa5gAKllPvbKtsjyxS39WdmWmqkmE42HOsVZaJWHVEttxbebel3zdpD5BSxWtRiG7NuZLNVedMUaK5AdgIRrJk1u"
}
I do not get the google profile, no user is added to my DB and I get this error:
{
"name": "GeneralError",
"message": "401 Unauthorized",
"code": 500,
"className": "general-error",
"data": {},
"errors": {}
}
I have added "google" to my list of authStrategies in default.json
So my question is what do I need to do?
So I found the solution. Thought I might share. Add this to authentication.js
//add this method
async getProfile(authResult) {
const accessToken = authResult.accessToken;
const { data } = await axios
.get(
`https://openidconnect.googleapis.com/v1/userinfo?access_token=${accessToken}`
)
.then((res) => {
return res;
})
.catch((error) => console.log("autherr", error));
return data;
}

Why am I getting different response from my data when local and when on heroku?

I am working on an Application which i have also deployed in heroku. The issue is that when I login in using heroku, user is nested inside a data object. but when I work locally or use postman, user isnt nested.
Help Please.
I get this response on the deployed version.
data: {
user: {
email: "my_email"
name: "my_name"
role: "user"
_id: "6205807deeadcfa734f954f3".
}
status: "success"
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYyMDU4MDdkZWVhZGNmYTczNGY5NTRmMyIsImlhdCI6MTY0NDg0NTYyMCwiZXhwIjoxNjQ1NDUwNDIwfQ.YeWFNrN8rsLPJvvU8JQDwBVG4aBqqEuo7ssgLrR3O8M"
But when I log in locally, I get the response as
user: {
email: "my_email"
name: "my_name"
role: "user"
_id: "6205807deeadcfa734f954f3".
}
status: "success"
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYyMDU4MDdkZWVhZGNmYTczNGY5NTRmMyIsImlhdCI
For Heroku, the USER is nested inside data but for local host and postman, the user isnt nested.
My codes are:
exports.login = catchAsync(async (req, res, next) => {
const { email, password } = req.body
if (!email || !password) {
return next(new AppError('Please provide email and password!', 400))
}
const user = await User.findOne({ email }).select('+password')
if (!user || !(await user.comparePassword(password, user.password))) {
return next(new AppError('Incorrect email or password', 401))
}
createSendToken(user, 200, req, res)
})
These are my api codes
const createSendToken = (user, statusCode, req, res) => {
const token = signToken(user._id)
res.cookie('jwt', token, {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRES_IN * 24 * 60 * 60 * 1000
),
httpOnly: true,
})
user.password = undefined
res.status(statusCode).json({
status: 'success',
token,
user,
})
}
For my react, The function code is:
function request(path, { data = null, token = null, method = 'GET' }) {
return (
fetch(`${process.env.REACT_APP_API}${path}`, {
method,
headers: {
Authorization: token ? `Bearer ${token}` : '',
'Content-Type': 'application/json',
},
body:
method !== 'GET' && method !== 'DELETE' ? JSON.stringify(data) : null,
})
.then((response) => {
// If Successful
if (response.ok) {
if (method === 'DELETE') {
// If delete, nothing returned
return true
}
return response.json()
}
// If errors
return response
.json()
.then((json) => {
// Handle Json Error response from server
if (response.status === 400) {
const errors = Object.keys(json).map(
(k) => `${json[k].join(' ')}`
)
throw new Error(errors.join(' '))
}
throw new Error(JSON.stringify(json))
})
.catch((e) => {
if (e.name === 'SyntaxError') {
throw new Error(response.statusText)
}
throw new Error(e)
})
})
.catch((e) => {
// Handle all errors
toast(e.message, { type: 'error' })
})
)
}
The main sign in function
export function signIn(email, password) {
return request('/api/v1/auth/login', {
data: { email, password },
method: 'POST',
})
}
Then I import this into my auth context and execute it there
import {signIn as signInApi} from '../apis'
const AuthContext = createContext()
export const AuthProvider = ({ children }) => {
const [token, setToken] = useState(localStorage.getItem('token'))
const [user, setUser] = useState(
JSON.parse(localStorage.getItem('user'))
)
const [loading, setLoading] = useState(false)
const signIn = async (email, password, callback) => {
setLoading(true)
const res = await signInApi(email, password)
if (res.token) {
localStorage.setItem('token', res.token)
localStorage.setItem('user', JSON.stringify(res.user)) // This stores the user in localhost but returns undefined for user in the one deployed to heroku. I have to use
localStorage.setItem('user', JSON.stringify(res.data.user)) which now works on the deployed one but not on the local one
setToken(res.token)
setUser(res.user)
callback()
}
setLoading(false)
}
}
it seems the deployed version is using built in implementaion of createSendToken and not the one you provided. need to check your project structure.
in order to validate this change the function name and the call createSendToken to something else and you will find the issue

NuxtServerInit sets Vuex auth state after reload

I'm setting a basic authentication on a Nuxt project with JWT token and cookies to be parsed by nuxtServerInit function.
On login with email/password, works as intended, setUser mutation is triggered and the appropriate user object is stored in state.auth.user.
On reload, nuxtServerInit will get the jwt token from req.headers.cookies, call the GET method and identify user.Works like a charm.
Problem starts when I hit the /logout endpoint. state.auth.user is set to false and Im effectively logged out... but If I refresh, I'm logged in again with the previous user data. Even if my cookies are properly empty (on below code, both user and cookie are undefined after logout and refresh, as expected)
So I really don't get why is my state.auth.user is back to its initial value...
store/index.js
import Vuex from "vuex";
import auth from "./modules/auth";
import axios from "~/plugins/axios";
const cookieparser = process.server ? require("cookieparser") : undefined;
const END_POINT = "api/users";
const createStore = () => {
return new Vuex.Store({
actions: {
async nuxtServerInit({ commit, dispatch}, { req }) {
let cookie = null;
console.log(req.headers.cookie)
if (req.headers.cookie) {
const parsed = cookieparser.parse(req.headers.cookie);
try {
cookie = JSON.parse(parsed.auth);
console.log("cookie", cookie)
const {accessToken} = cookie
const config = {
headers: {
Authorization: `Bearer ${accessToken}`
}
}
const response = await axios.get(`${END_POINT}/current`, config)
const user = response.data
console.log("user nuxt server init", user)
await commit('setUser', user)
} catch (err) {
// No valid cookie found
console.log(err);
}
}
}
},
modules: {
auth
}
});
};
export default createStore;
modules/auth.js
import axios from "~/plugins/axios";
const Cookie = process.client ? require("js-cookie") : undefined;
const END_POINT = "api/users";
export default {
state: {
user: null,
errors: {}
},
getters: {
isAuth: state => !!state.user
},
actions: {
login({ commit }, payload) {
axios
.post(`${END_POINT}/login`, payload)
.then(({ data }) => {
const { user, accessToken } = data;
const auth = { accessToken };
Cookie.set("auth", auth);
commit("setUser", user);
})
.catch(e => {
const error = e;
console.log(e);
commit("setError", error);
});
},
logout({ commit }) {
axios
.post(`${END_POINT}/logout`)
.then(({ data }) => {
Cookie.remove("auth");
commit("setUser", false);
})
.catch(e => console.log(e));
},
},
mutations: {
setUser(state, user) {
state.user = user;
},
setError(state, errors) {
state.errors = errors;
}
}
};
The way I logout my user is by creating a mutation called clearToken and commit to it in the action :
State :
token: null,
Mutations :
clearToken(state) {
state.token = null
},
Actions :
logout(context) {
context.commit('clearToken')
Cookie.remove('token')
}
This way, you token state revert back to null.

Categories

Resources