After reading the following post, https://dev.to/chrsgrrtt/easy-user-authentication-with-next-js-18oe and consulting the following question Using next-iron-session's "withIronSession" with Next.JS to perform simple authentication, I am still unable to access the session using req.session.get('user'). Below is my implementation in a Next.js project:
Create a util
import {withIronSession} from 'next-iron-session';
const cookie = {
cookieName: process.env.COOKIE_NAME,
password: process.env.COOKIE_SECRET,
cookieOptions: {secure: process.env.NODE_ENV === 'production'},
};
export const guard = (handler) => {
return withIronSession(handler, cookie);
};
export default cookie;
Create an API endpoint
const zlib = require('zlib');
import cookie from '#/utils/cookie';
const fetch = require('node-fetch');
import {withIronSession} from 'next-iron-session';
export default withIronSession(
async (req, res) => {
if (req.method === 'POST') {
try {
const request = await fetch(
process.env.NEXT_PUBLIC_API_BASE_URL + '/api/login',
{
method: 'post',
body: req.body,
headers: {
'Content-Type': 'application/json',
'Origin': req.headers.host || req.headers.origin,
},
}
);
const response = await request.text();
const {success, data, message} = JSON.parse(response);
// set JWT in session
compressor(data, (x) => req.session.set('user', x));
// persist session value
await req.session.save();
// console.log(req.session.get('user'));
return res.status(201).json({success, message});
} catch (error) {
console.log(error);
}
}
return res.status(404).json('Not found');
},
cookie
);
Access session data in a page
export const getServerSideProps = guard(async (ctx) => {
const {req} = ctx;
const session = req.session.get();
console.log({session});
return {redirect: {destination: '/sign-in', permanent: false}};
});
The above terminal log gives an empty object. Is there something am doing wrong??
Try the following:
export const getServerSideProps = guard(async function ({
req,
res,
query,
}) {
//Assuming you have "user" session object
const user = req.session.get("user");
...
});
Harel
Related
Please I need a help on how to fetch a data from node to react, I have been stuck here for 2 weeks now.
Here are my backend code:
server.js:
require("dotenv").config();
const app = require("./src/app");
const port = process.env.PORT || 4000;
app.get("/", (req, res) => {
res.send("Hello World!");
});
app.listen(port, () => {
console.log(`Server is running on port http://localhost:${port}`);
});
app.js:
const express = require("express");
const cors = require("cors");
const cookieSession = require("cookie-session");
const app = express();
app.use(
cors({
origin: ["http://localhost:4000/api", "http://localhost:3000"],
})
);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use(express.json());
app.use(express({ type: "application/vnd.api+json" }));
app.use(express.urlencoded({ extended: true }));
app.use(
cookieSession({
name: process.env.COOKIE_NAME, //ookie name in .env
secret: process.env.COOKIE_SECRET, //secret name in .env
httpOnly: true,
sameSite: "strict",
maxAge: 24 * 60 * 60 * 1000, // 24 hours duration before expire
})
);
app.use("/uploads", express.static("uploads"));
const jobRoute = require("./routes/job.routes");
app.use("/api/", jobRoute);
module.exports = app;
service.js:
const db = require("../config/database");
const notificationServices = require("./notification.services");
const { jobReuseQuery } = require("../job reuseable query/job.queries");
const createJob = async (body) => {
const {
title,
salary_type,
salary,
job_types,
description,
company_id,
sector_id,
category_id,
} = body;
const { rows } = await db.query(
`INSERT INTO jobs (title, salary_type, salary, job_types, description, company_id, sector_id, category_id)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *`,
[
title,
salary_type,
salary,
job_types,
description,
company_id,
sector_id,
category_id,
]
);
notificationServices.sendMatchJobsToUserProfiles(rows[0]);
return rows[0];
};
const getAllJobs = async () => {
const { rows } = await db.query("SELECT * FROM jobs");
return rows;
};
controller.js:
const jobService = require("../services/job.services");
const createJob = async (req, res) => {
try {
const job = await jobService.createJob(req.body);
res.status(201).send({
message: "Job created successfully",
data: job,
});
} catch (err) {
res.status(400).send(err.message);
}
};
const getAllJobs = async (req, res) => {
try {
const jobs = await jobService.getAllJobs();
res.status(200).send({ data: jobs });
} catch (err) {
res.status(400).send({ message: err.message });
}
};
routes.js:
const router = require("express-promise-router")();
const jobController = require("../controllers/job.controller");
const auth = require("../middleware/auth.middleware");
router.post("/jobs", auth, jobController.createJob);
auth.js:
const db = require("../config/database");
const jwt = require("jsonwebtoken");
const dotenv = require("dotenv");
dotenv.config();
const auth = async (req, res, next) => {
const token = req.session.token;
if (!token) {
return res.status(401).send({ error: "Please Authenticate" });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const { rows } = await db.query("SELECT * FROM users WHERE id = $1", [
decoded.id,
]);
if (!rows[0]) {
throw new Error("User not found");
}
req.user = rows[0];
next();
} catch (error) {
return res.status(401).send({ error: error.message });
}
};
module.exports = auth;
React frontend code:
import React, { useEffect } from "react";
import tech from "../../image/tech-big.svg";
import health from "../../image/health-big.svg";
import eng from "../../image/eng-big.svg";
import axios from "axios";
import { useState } from "react";
const Joblist = () => {
const [name, setName] = useState([]);
//first method
const response = axios
.get("http://localhost:4000/api/jobs/")
.then((res) => res.json());
console.log(response);
//second method
const fetchData = async () => {
const newData = await fetch("http:localhost:4000/api/jobs", {
method: "GET",
headers: {
"Content-Type": "application/json",
ACCEPT: "application/json",
"Access-Control-Allow-Credentials": true,
"Access-Control-Allow-Origin": true,
credentials: "same-origin",
Authorization: `Bearer ${token}`,
},
}).then((res) => res.json());
console.log(newData);
setName(newData.jobs.name);
fetchData();
};
you can see in my react, I have 2 method i used trying to fetch the data fron node to the react
first method return error in my browser console :
Promise {<pending>}
GET http://localhost:4000/api/jobs/ 401 (Unauthorized)
Uncaught (in promise) AxiosError {message: 'Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
while the second method return nothing in my browser console
I am trying to fetch a data from my node backend into frontend react but my first method log error while the second method log nothing
I think you need to clean up a bit your setting, since you're using CORS than you can first make some changes :
// .....
const app = express();
// with CORS you can do all your setting at the same place, so you don't need to set the header
const corsOptions = {
origin: ["http://localhost:4000/api", "http://localhost:3000"],
methods: "GET, POST, PUT, DELETE, OPTIONS, HEAD",
credentials: true, // for jwt/cookie !
};
app.use(cors(corsOptions));
app.use(express.json());
app.use(express({ type: "application/vnd.api+json" }));
app.use(express.urlencoded({ extended: true }));
app.use(
cookieSession({
name: process.env.COOKIE_NAME,
secret: process.env.COOKIE_SECRET,
maxAge: 24 * 60 * 60 * 1000,
httpOnly: true,
sameSite: false, //set this to "None" if you deploy to production on cross domaine.
secure: false, //set to true is required on production with https
});
app.use("/uploads", express.static("uploads"));
const jobRoute = require("./routes/job.routes");
app.use("/api/", jobRoute);
module.exports = app;
Update the fetch part I clean up (I remove the header) and i just notice on your job.controller.js you put data property on your response json.. so you need to check again your database structure if it's still not working.
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("http:localhost:4000/api/jobs", {
credentials: "include", //to be able to send with cookies...
});
if(response.ok) {
const newData = await response.json();
console.log(newData);
setName(newData.data.jobs.name); // this part you need to check your data structure again...
}
} catch (error) {
console.log(error)
}
}
fetchData();
}, []);
Optional note: this part is not part of your question, just in case if there is still issue with the cookie-session and jwtoken, you can change how the JWT is stored in the cookie: cookie-session purpose is to create a "session id" to authenticate the user by storing it at the client side (on the browser, with the cookie), i don't really see the point to use this if you're gonna use jwt token to authenticate anyway ? I let you see the step below if you re still stuck at this part:
First, you may need to install cookie-parser middleware, because if this method work for you, you will be able to uninstall cookie-session.
const cookieParser = require('cookie-parser')
/...
app.use(cookieParser());
on the auth.controllers.js
const loginAuth = async (req, res) => {
try {
const token = await authServices.login(req.body);
// set the jwt token on the cookie
res.cookie("jwt", token, {
maxAge: 24 * 60 * 60 * 1000,
httpOnly: true,
sameSite: false, //set this to "None" if you deploy to production on cross domaine.
secure: false, //set to true is required on production with https
})
return res.status(200).json({
//controller will return this message if the body sent was match
message: "User logged in successfully!",
});
} catch (error) {
//ratther it will return this erroe message
return res.status(500).json({ message: error.message });
}
};
//create a logout session for the user to logout by signing session to null
const logoutAuth = async (req, res) => {
res.clearCookie("jwt")
return res.status(200).send({ message: "User logged out successfully!" });
};
You also need to replace const token = req.session.token; in your activeAuth function, and in your auth.middleware.js at the auth middleware function by this:
const token = req.cookies["jwt"] //or
const token = req.cookies.jwt
Finally if it work you can uninstall cookie-session.
I am building a login page with Mobx, MUI V5, react-router V6 and react-hook-form.
My first API call is to authenticate the application, apiAuth() will return a token that needs to be passed to all subsequent API calls.
On the next call, userAuth(), I try to validate the user credential.
As you can see, the method takes 3 arguments (a token, card number and, password)
When the user credentials are valid, I can login successfully.
When the user credentials are not valid on the first try, it works as
expected. I receive 400 (Bad Request) error from the API and display the error message on the
interface.
That said when I entered the user credentials once more, I get a 401 (Unauthorized) error.
Upon further inspection of the request headers, when I compared the authorization header in both userAuth() calls, I see that the token's value on the second call was concatenated with the previous token
Any ideas as to why for this behavior?
My AuthStore looks as follow:
class AuthStore {
isAuth = false
isAuthFail = false
AuthFailObj = {}
bearerToken = ''
cardNum = ''
password=''
constructor() {
makeObservable(this, {
isAuth: observable,
AuthFailObj: observable,
isAuthFail:observable,
bearerToken: observable,
cardNum: observable,
password: observable,
auth: action,
setIsAuth: action,
setToken: action,
setCardNum: action,
setPassword: action,
setIsAuthFail: action,
setAuthFailObj: action
})
}
setIsAuth = isAuth => {
this.isAuth = isAuth
}
setToken = bearerToken => {
this.bearerToken = bearerToken
}
setCardNum = cardNum => {
this.cardNum = cardNum
}
setPassword = password => {
this.password = password
}
setIsAuthFail = b => {
this.isAuthFail = b
}
setAuthFailObj = ojb => {
this.AuthFailObj = ojb
}
auth = async () => {
const apiRes = await apiAuth()
if (apiRes.status === 200){
const apiData = await apiRes.text()
this.setToken(JSON.parse(apiData)[0].token)
}
const userAuthRes = await userAuth(this.bearerToken, this.password, this.cardNum)
if (!userAuthRes.ok){
this.setIsAuthFail(true)
const errRes = await userAuthRes.text()
userAuthRes.status === 400 && this.setAuthFailObj(JSON.parse(errRes))
userAuthRes.status === 401 && this.setAuthFailObj('401 (Unauthorized)')
}
if (userAuthRes.ok){
const userAuthData = await userAuthRes.text()
userStore.updateUserProfile(JSON.parse(userAuthData))
this.setIsAuth(true)
}
}
}
export default new AuthStore()
In the login form, the submit method looks like this:
const submit = async (data) => {
AuthStore.setCardNum(data.Card_Number)
AuthStore.setPassword(data.Password)
setToggle(true)
await AuthStore.auth()
if (AuthStore.isAuth) {
navigate('/dashboard')
} else {
// clear form
}
}
Finally, the PrivateRoute logic reads is simple:
const PrivateRoute = () => {
return AuthStore.isAuth ? <Outlet /> : <Navigate to='/' />
}
The function userAuth()
const myHeaders = new window.Headers()
const { REACT_APP_API_ACC_MNG_AUTH_URL } = process.env
const userAuth = async (bearerToken, password, cardNum) => {
myHeaders.append('Authorization', `Bearer ${bearerToken}`)
myHeaders.append('Content-Type', 'application/json')
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
})
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
}
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions)
return response
}
The issue is that you're using the Headers API and appending to the headers instead of setting them, which exist outside the function scope and are updated. From MDN:
The append() method of the Headers interface appends a new value onto an existing header inside a Headers object, or adds the header if it does not already exist.
So every time you make a request, if you append the header, it will be added on to the existing value. You could move your headers declaration inside of the function, and create a new object each time you make a request:
const { REACT_APP_API_ACC_MNG_AUTH_URL } = process.env
const userAuth = async (bearerToken, password, cardNum) => {
const myHeaders = new window.Headers()
myHeaders.append('Authorization', `Bearer ${bearerToken}`)
myHeaders.append('Content-Type', 'application/json')
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
})
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
}
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions)
return response
}
Or you could just pass them in as an object, which is allowed by the Fetch API:
const userAuth = async (bearerToken, password, cardNum) => {
const raw = JSON.stringify({
cardNumber: cardNum,
pinNumber: password
});
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow',
headers: {
'Authorization': `Bearer ${bearerToken}`,
'Content-Type': 'application/json',
}
};
const response = await window.fetch(REACT_APP_API_ACC_MNG_AUTH_URL, requestOptions);
return response;
}
I get 401 error after a while when the page is reloaded, I figured it could be because the access token is expired. How do I set a new token with my refresh token? The below function runs every time the user visits a new page or refreshes the page. But it doesn't seem to work.
export async function currentAccount() {
if (store.get('refreshToken')) {
const query = {
grant_type: 'refresh_token',
companyId: store.get('lastCompanyId'),
refresh_token: store.get('refreshToken'),
}
const queryString = new URLSearchParams(query).toString()
const actionUrl = `${REACT_APP_SERVER_URL}/login?${queryString}`
return apiClient
.post(actionUrl, { auth: 'basic' })
.then(async response => {
if (response) {
const { access_token: accessToken } = response.data
store.set('accessToken', accessToken)
return response.data
}
return false
})
.catch(err => {
console.log('error', err)
store.clearAll()
})
}
return false
}
Login sets the access tokens
export async function login(email, password) {
const query = {
grant_type: 'password',
username: email,
password,
}
const queryString = new URLSearchParams(query).toString()
const actionUrl = `${REACT_APP_SERVER_URL}/login?${queryString}`
return apiClient
.post(actionUrl, { auth: 'basic' })
.then(async response => {
if (response) {
const {
data: {
access_token: accessToken,
refresh_token: refreshToken,
},
} = response
const decoded = jsonwebtoken.decode(accessToken)
response.data.authUser = decoded.authUser
const { userId, profileId, companyId } = decoded.authUser
if (accessToken) {
store.set('accessToken', accessToken)
store.set('refreshToken', refreshToken)
}
return response.data
}
return false
})
.catch(err => console.log(err))
}
saga users.js
export function* LOAD_CURRENT_ACCOUNT() {
yield put({
type: 'user/SET_STATE',
payload: {
loading: true,
},
})
const { authProvider } = yield select((state) => state.settings)
const response = yield call(mapAuthProviders[authProvider].currentAccount)
if (response) {
const decoded = jsonwebtoken.decode(response.access_token)
response.authUser = decoded.authUser
yield store.set('id', id)
try {
const user = yield call(LoadUserProfile)
if (user) {
const { company } = user
yield put({
type: 'user/SET_STATE',
payload: {
...user,
preferredDateFormat: user.preferredDateFormat || 'DD/MM/YYYY',
userId,
id,
},
})
}
} catch (error) {
}
}else{
store.set('refreshToken', response.refreshToken)
}
yield put({
type: 'user/SET_STATE',
payload: {
loading: false,
},
})
}
You can get a new access token with your refresh token using interceptors. Intercept and check for response status code 401, and get a new access token with your refresh token and add the new access token to the header.
Example:
return apiClient
.post(actionUrl, { auth: 'basic' })
.then(async response => {
if (response) { // check for the status code 401 and make call with refresh token to get new access token and set in the auth header
const { access_token: accessToken } = response.data
store.set('accessToken', accessToken)
return response.data
}
return false
});
Simple Interceptor example,
axios.interceptors.request.use(req => {
req.headers.authorization = 'token';
return req;
});
Interceptor example for 401
axios.interceptors.response.use(response => response, error => {
if (error.response.status === 401) {
// Fetch new access token with your refresh token
// set the auth header with the new access token fetched
}
});
There are several good posts on Interceptors usage for getting a new access token with your refresh token
https://thedutchlab.com/blog/using-axios-interceptors-for-refreshing-your-api-token
https://medium.com/swlh/handling-access-and-refresh-tokens-using-axios-interceptors-3970b601a5da
Automating access token refreshing via interceptors in axios
https://stackoverflow.com/a/52737325/8370370
The above answer is good. But I found below method is better than that also using Axios Interceptors and "jwt-decode". Give it a try. (I'm using session storage for this example. You can use your own way to store the tokens securely)
Methodology
Login to get an access token and long live refresh token and then store them securely.
Create an axios instance to check the access token expiration with "jwt-decode". Then add the access token into the request if there is a valid access token, or else request a new access token using the stored refresh token and then apply the new access token into the request.
Login:
import axios from 'axios'
const handleLogin = async (login) => {
await axios
.post('/api/login', login, {
headers: {
'Content-Type': 'application/json'
}
})
.then(async response => {
sessionStorage.setItem('accessToken', response.data.accessToken)
sessionStorage.setItem('refreshToken', response.data.refreshToken)
})
.catch(err => {
if (errorCallback) errorCallback(err)
})
}
Create axios instance:
import axios from 'axios'
import jwt_decode from 'jwt-decode'
import dayjs from 'dayjs'
const axiosInstance = axios.create({
headers: { 'Content-Type': 'application/json' }
})
axiosInstance.interceptors.request.use(async req => {
const accessToken = sessionStorage.getItem('accessToken') ? sessionStorage.getItem('accessToken') : null
if (accessToken) {
req.headers.Authorization = `Bearer ${accessToken}`
}
const tokenData = jwt_decode(accessToken)
const isExpired = dayjs.unix(tokenData.exp).diff(dayjs()) < 1
if (!isExpired) return req
const refreshToken = sessionStorage.getItem('refreshToken')
const response = await axios.post('/api/refresh', { refreshToken }, {
headers: {
'Content-Type': 'application/json'
}
})
req.headers.Authorization = `Bearer ${response.data.accessToken}`
sessionStorage.setItem('accessToken', response.data.accessToken)
return req
})
export default axiosInstance
Use axios instance in all the requests (Redux Toolkit Example):
import { createSlice, createAsyncThunk } from '#reduxjs/toolkit'
// Import axiosInstance
import axiosInstance from 'src/utils/axiosInstance'
export const getItems = createAsyncThunk(
'appItems/getItems',
async (args, { rejectedWithValue }) => {
try {
const response = await axiosInstance.get('/api/items')
return response.data
} catch ({ response }) {
return rejectedWithValue({ code: response.status, ...response.data })
}
}
)
Currently, when I authenticate a user with firebase, I store their auth token in localStorage to be used later to connect to my backend like so:
const httpLink = new HttpLink({uri: 'http://localhost:9000/graphql'})
const authMiddleware = new ApolloLink((operation, forward) => {
// add the authorization token to the headers
const token = localStorage.getItem(AUTH_TOKEN) || null
operation.setContext({
headers: {
authorization: token ? `Bearer ${token}` : ''
}
})
return forward(operation)
})
const authAfterware = onError(({networkError}) => {
if (networkError.statusCode === 401) AuthService.signout()
})
function createApolloClient() {
return new ApolloClient({
cache: new InMemoryCache(),
link: authMiddleware.concat(authAfterware).concat(httpLink)
})
}
My problem with this is that I have no way to refresh the token once it expires. So I tried to use the following to set the authorization token for apollo:
const httpLink = new HttpLink({uri: 'http://localhost:9000/graphql'})
const asyncAuthLink = setContext(
() => {
return new Promise((success, reject) => {
firebase.auth().currentUser.getToken().then(token => {
success({
headers: {
authorization: token ? `Bearer ${token}` : ''
}
})
}).catch(error => {
reject(error)
})
})
}
)
const authAfterware = onError(({networkError}) => {
if (networkError.statusCode === 401) AuthService.signout()
})
function createApolloClient() {
return new ApolloClient({
cache: new InMemoryCache(),
link: asyncAuthLink.concat(authAfterware.concat(httpLink))
})
}
This works when the user first authenticates, but once the user refreshes the page, firebase is no longer initialized when my graphql queries are sent to my backend, so the token is not sent with it. Is there a way I can asynchronously wait for firebase.auth().currentUser so this will work? Or is there another approach I should take entirely? As far as I know (100% sure) currentUser.getIdToken only makes a network call if the current token is no longer valid. I think this is acceptable as in cases where the token is not valid, the backend can't respond anyway, so I will need to wait for a token refresh to continue.
Some other ideas I thought of:
Continue to use localStorage to store the auth token, refresh it in authAfterware if my backend sends a 401 response back and retry the request.
Set a delay on getting the auth token (not desirable)
Any other ideas?
Thanks!
I know is a bit late but I was stuck on that as well and found a way to solve it. Maybe is not the best one but at least it works.
My approach is to create a Next api endpoint to retrieve the user token using the getUserFromCookies method:
import { NextApiRequest, NextApiResponse } from "next";
import { getUserFromCookies } from "next-firebase-auth";
import initAuth from "../../utils/initAuth";
initAuth();
const handler = async (req: NextApiRequest, res: NextApiResponse<any>) => {
try {
const user = await getUserFromCookies({ req, includeToken: true });
const accessToken = await user.getIdToken();
return res.status(200).json({ success: true, accessToken });
} catch (e) {
console.log(`${e}`);
return res.status(500).json({ error: `Unexpected error. ${e}` });
}
};
export default handler;
And then call this endpoint in the apollo client config like that:
import { ApolloClient, InMemoryCache, ApolloLink, HttpLink, concat } from "#apollo/client";
import { setContext } from "#apollo/client/link/context";
import { relayStylePagination } from "#apollo/client/utilities";
const getUserToken = async () => {
const res = await fetch("http://localhost:3000/api/get-user-token");
const { accessToken } = await res.json();
return accessToken;
};
const asyncAuthLink = setContext(async (request) => {
const token = await getUserToken();
return { ...request, headers: { authorization: token ? `Bearer ${token}` : "" } };
});
const httpLink = new HttpLink({ uri: process.env.NEXT_PUBLIC_API_URL });
const client = new ApolloClient({
name: "web",
version: "1.0",
uri: process.env.NEXT_PUBLIC_API_URL,
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
users: relayStylePagination(),
},
},
},
}),
link: concat(asyncAuthLink, httpLink),
});
export default client;
So I am trying to create a user using redux-form. I have an express post route on the backend. NOTE: using redux-thunk for middleware, whatwg-fetch with webpack and babel-polyfill.
routes.post('/signup', async (req, res) => {
try {
const createdUser = await userController.createUser(req.body);
const JSONCreatedUser = JSON.stringify(createdUser);
res.json({
confirmation: 'success',
result: createdUser,
});
return JSONCreatedUser;
} catch (error) {
res.statusMessage = error.toString();
res.status(409).json({
confirmation: 'failure',
error: error.toString(),
});
}
});
So the problem I am having is that when I use postman. I will get the entire user object back.
But when I submit it using form I only get
Apimanager.js
export const signUserUpApi = async (url, params) => {
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
const { status, statusText } = response;
if (status === 409) {
throw new Error(statusText);
}
return response;
} catch (error) {
throw new Error(error.toString());
}
};
action.js
import constants from '../constants';
import { signUserUpApi } from '../utils/APIManager';
const signUserUpUrl = process.env.SIGN_USER_UP_URL || 'http://localhost:3000/user/signup';
export const signUserUp = (user) => {
return async (dispatch) => {
try {
const createdUser = await signUserUpApi(signUserUpUrl, user);
dispatch({
type: constants.SIGN_USER_UP,
user: createdUser,
});
return createdUser;
} catch (error) {
throw new Error(error);
}
};
};
export const signUserIn = (user) => {
return {
type: constants.SIGN_USER_UP,
user,
};
};
What I am trying to do is to get the User Object I created when I submit the form and redirect back to the page.
This is what I get back and it did create the user.
First thing, I need is why am I getting the https status code back and not the user object?
Second thing, what are the ways to redirect to the home page when a user successfully signed up logged in.