Next Js Api routes response helpers (redirect) - javascript

I'M trying to create a login functionality in Next js.
Everything is pretty much done but I'm unable to redirect to homepage after login.
I'm using Next js with sanity as headless CMS
This is my login api
export default async function CreateComment(req, res) {
const { email, password , user } = JSON.parse(req.body)
console.log(password , "123")
const Alluser = user.map((item)=>{
return item.email
})
const UserPassword = user.map((item)=>{
return item.password
})
if (Alluser.includes(email) && UserPassword == password){
console.log(email)
}
res.redirect(307, '/').status(200).send('Success')
}
After Login Error in terminal
Response in network #1
Response in network #2

Use the redirect as follows
res.redirect(307, '/');
Redirects to a specified path or URL

Related

How to add authorization header to a react download button?

I have a button where the logged user can download a file which is stored in the database and is fetched by react from node js/express js. Without authentication I can easily do that by just an tag. But with authentication I am struggling a lot.
React:
const handleDownload = async () => {
const result = await fetch (process.env.REACT_APP_BACKEND_URL + `/files/download/${props.id}`, {
headers: {'Authorization': auth.token}
});
const responseData = await result.json();
return responseData;
}
return (
<button onClick={handleDownload}>Download File</button>
)
Express js:
router.get('/download/:fid', filesControllers.downloadFile);
const downloadFile = async (req, res, next) => {
const fileId = req.params.fid;
let filePost;
try {
filePost = await File.findById(fileId);
} catch (err) {
return next(new HttpError("Error", 500));
}
console.log(filePost.file);
res.download(filePost.file);
};
possible solutions:
verify that your auth.token really contains the token (try a
console.log for example)
if you're using a bearer token do this: {'Authorization': "Bearer
"+auth.token}
from backend side you will need to do some changes learn jwt authentication or anyother authentication technique for backend and make sure that it works with frontend
how this app will work is when user is not logged in and he clicks on download backend verifies the token and if token is invalid or doesnt exist it send the error through resopnse and frontend shows it on ui

How can I email links work on the front end?

I have built some functionality into my API that sends a verification email to a user and then when a get request is made to the route the user then becomes active and can be used to login. In order to make this work on the front end I have used a res.redirect which takes me to the login page.
The problem, however, is that this means that when I want to replicate this journey in postman I then receive a load of html rather than a formatted json response. So my question is, is there a way that we can handle this request so that, depending on where it is called, a different response is sent back? As I do not think an event listener will work in the case of an email.
For context, my application uses nodejs, mongodb and pug templates.
`exports.signup = catchAsync(async (req, res, next) => {
const { token } = req.params;
const { email } = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findOne({ email });
if (!user || !((await user.signUpId) === token)) {
return next(new AppError('Invalid link', 401));
}
user.ready = true;
user.singUpId = undefined;
await user.save({ validateBeforeSave: false });
const url = `${req.protocol}://${req.get('host')}/me`;
await new Email(user, url).sendWelcome();
await res.redirect('http://localhost:5000/login');
});`

Problem maintaining session data with Vue JS and Sails JS

Session information is not being maintained when APIs invoked via the VueJs.
In the sails backend, login action set the user id to the session. Whereas in the sessionAuth policy I am simply checking for the user id in the req session.
module.exports = async function (req, res, next) {
// User is allowed, proceed to the next policy,
// or if this is the last policy, the controller
const id = req.session.userId;
if (id) {
const user = await User.findOne({ id });
req.user = user;
if (user) {
return next();
}
}
// User is not allowed
// (default res.forbidden() behavior can be overridden in `config/403.js`)
return res.forbidden('You are not permitted to perform this action.');
};
The above policy works perfectly when requests are being made from Postmen. I invoke login action, any action invoked after that does have user id set in the session. But if the same sequence is followed in a web application user id is missing from the session even after the successful login.
Login component
axios.post(`${this.$config.baseUrl}/login`, this.user)
.then(res => {
this.$router.push({ path: "/home" });
})
Component accessing secured data
const response = await axios.get(`${baseUrl}/course`
return { courseList: response.data };
}

Express.js routing: how to prevent reloading of previous page?

I am new to express (or web development in general) and have a question about routing.
I am creating a web app on Firebase with pure JS, and am using routing on Firebase cloud functions. The routing part looks like below. The purpose is, when URL is in the form of /xxxxxx, it sends the profile html page, and when URL is for of r/xxxxx, it sends the posts html page. Then client-side rendering will be done to populate the additional data to make up a page. Below is the part of the code:
exports.webAPI = functions.https.onRequest(app);
app.get('/:id', (req, res) => {
res.set('Cache-Control', 'public, max-age=86400, s-maxage=86400');
res.status(200).sendFile(path.join(__dirname+'/app/profile.html'));
});
app.get('/r/:post', (req, res) => {
res.set('Cache-Control', 'public, max-age=86400, s-maxage=86400');
res.status(200).sendFile(path.join(__dirname+'/app/post.html'));
});
The issue is: whenever the user clicks on a post and then goes back to the profile page, the whole page is re-rendered. This is understandably very bad for user experience in the world of modern web app.
The question: how do I prevent reloading of previous page, unless there is a meaningful change to it(e.g. new post uploaded?)? Is there a way to do it in Express?
If there is a better version of code to do this, let me know . If I need to look at certain parts of the documentation, please advise. Or, if this is not possible with Express and I should look at something else, do guide me on where to look at.
Thanks!
Install axios package. In my scenario i am trying to register a form. So this all things i need to do for register without refreshing the page.
const register = async (name, email, password, passwordConfirm) => {
try {
const res = await axios({
method: "POST",
url: "your url",
data: {
name,
email,
password,
passwordConfirm
}
});
console.log(res);
if (res.data.status === "success") {
alert("You are registered succesfully");
window.setTimeout(() => {
location.assign("/");
}, 1500);
}
} catch (error) {
alert(error.response.data.message);
console.log(error);
}
};
document.querySelector("#registerform").addEventListener("submit", e => {
e.preventDefault();
const name = document.getElementById("name").value;
const email = document.getElementById("email").value;
const password = document.getElementById("password").value;
const passwordConfirm = document.getElementById("confirmPassword")
.value;
register(name, email, password, passwordConfirm);
});
Note: e.preventdefault plays major role.

How to use JWT in Client with AJAX

My application is a Node.js API with a client inside the same application.
I'm trying to implement a simple auth login that uses a JWT token generated by a Node.js API.
My logic is as follows:
Client: User submits login information to /auth/login route.
$.ajax({
url: "/auth/login",
type: "POST",
data: formData,
dataType: "json",
success: function(data, textStatus, jqXHR) {
if (typeof data.redirect == "string") {
window.location = data.redirect;
}
},
error: function(data) {
if (typeof fail === "function") fail(data);
}
});
API: Verify user and on success generates JWT and sends back to the client.
router.post("/login", async (req, res) => {
var login = { UID: req.body.UID, password: req.body.password };
AU.manualLogin(login)
.then(result => {
res.header("x-auth-token", result.token).json({
status: 200,
message: "success",
data: result.data,
redirect: "/dashboard"
});
})
.catch(err => next({ status: 400, message: err.message }));
});
Client: Saves JWT to the header and checks for redirect - In this case, I use window.location to direct to /dashboard after successful login. (this part I'm not sure about)
API: Middleware checks valid JWT on protected routes.
module.exports = function auth(req, res, next) {
const token = req.headers["x-auth-token"];
if (!token)
return res.status(401).send("Access denied. No token provided.");
try {
const decoded = jwt.verify(token, "jwtPrivateKey");
req.user = decoded;
next(); //pass control to next middleware
} catch (ex) {
res.status(400).send("Invalid token.");
}
};
The Problem:
The token is definitely being sent from API -> Client. But I have no idea how to handle the token from the client-side. I think the issue might be to do with the window.location redirect as at this point it does not seem to be sending the x-auth-token to the API.
What I have tried
I have tested the solution with Postman from end-to-end and it works fine. That probably proves that it isn't the API side that has the issue.
I've also tried these sources:
Pass request headers in a jQuery AJAX GET call
Adding custom header in HTTP before redirect
How to add header to request in Jquery Ajax?
jwt on node - how does the client pass the token back to the server
You need kind of a storage to keep the token. Otherwise the user has always to login again after he closes the browser/tab. So it's quite common to keep the token in local or session storage.
Approach 1: Use a single page application (SPA) framework like angular, vue.js, react etc. to protect your routes client-side
Approach 2: You can request only html and css (view) from your backend and then store the token after a login procedure. With a valid token, fetch the (protected) data with ajax requests. Redirect to the login page if a ajax request returns the status code 401 (unauthorized) or a user wants to access the protected route without having a token stored. This is perhaps the most suitable for you.
Approach 3: Use Node.js with a backend framework like express and store auth information in a server side session
index.js
const express = require('express');
const session = require('express-session');
const app = express();
app.use(require("cookie-parser")());
app.use(session({ secret: 'aslwezoweasdfasdlkfalksdfhweelaerfcv', resave: false, saveUninitialized: true}));
routes/protectedRoutes.js
const express = require('express');
const router = express.Router();
router.all("/*", util.handleAuthenticate); // check auth on every request
// other routes
indexController.js (login functionality)
module.exports.login = function(req, res) {
if(!req.session.name) {
// check username/password --> db lookup
// if valid:
req.session.name = ...
// redirect to home or backref
// else: redirect to login
}
}
util/security.js
function isLoggedIn(req) {
return !!req.session.name;
}
function handleAuthenticate(req, res, next) {
if(isLoggedIn(req))
{
next();
}
else
{
// redirect to login page
}
}

Categories