404 error on post request in ec2 server - api

I deployed my mean stack project to amazon ec2 instance and i tried to login and it returns me 404 error (Cannot POST /api/user/login). Both the client side and server side code is inside the same project. When i run the project from localhost it works fine. What could be the issue ? Thanks.
Edit : Code snipped added
From controller
var credentials = {
email : $scope.user.email,
password : $scope.user.password
};
User.login(credentials)
.then(function (response) {
// Administrator. Redirect to /admin.html page
if($cookies.get('userType') == 0) {
$location.path('/admin');
}
console.log("From controller "+ response);
})
.catch(function(error) {
console.log(error);
})
From service
$http({
method : 'POST',
url : '/api/user/login',
data : data
})
.success(function (data, status, headers, config) {
object = JSON.parse(Util.toObject(data));console.log(object._id);
$cookies.put('userType', object['status']); // 0 for admin
$cookies.put('email', object.email); // store the email for session.
console.log(object['status'] + ' ' + object.email);
$('#loginModal').hide();
deffered.resolve(Util.toObject(data));
})
.error(function (data, status, headers, config) {
console.log("Error in Login "+ status);
deffered.reject(data);
})
BE route
app.use('/api/admin', require('./admin'));
Inside admin folder, index.js file
router.post('/login', controller.login);
controller.login file
exports.login = function(req, res) {
console.log(req.body);
User.find(req.body, function(err, data) {
if (err) {
console.log(' Error in finding the data .. ');
}
else {
console.log(' Data found in login ' + JSON.stringify(data));
res.status(200).json(data);
}
});
};

Found the issue in the end. I added '/' at the end of each API endpoint and it worked.

Related

how to access exceptions thrown by Nestjs from frontend?

I am building backend API with Nestjs and I want to access exeptions from frontend
this is a simple example from login endpoint when user enters non-existent email :
const user = await this.userModel.findOne({ email });
if (!user) {
throw new NotFoundException('email does not exist .');
}
now when I send request from my Nextjs application like this :
await axios
.post(`http://127.0.0.1:5000/user/login`, {
email: values.email,
password: values.password,
})
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log("Login catched an error : ", error);
});
I get the NotFoundException as error:
now I want to get the status of this error (404 in this case),is it possible ?
It's an AxiosError, so you should be able to access error.response.status as shown in Axios's documentation

Next.js How to protect my website routes to authenticated users with NextAuth

I want to protect all routes from my NextJs website to authenticated users with NextAuth except the login route that can be accessed with being authenticated, I tried making a middleware that checks for user token, and redirect them to the login route if it was unavailable. but a general middleware for that would stop the website from getting public files so i came up with this:
// middleware.js
import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt'
export default async function middlware(req) {
// ignoring file system and public folder
if (req.nextUrl.pathname.startsWith('/_next/') ||
req.nextUrl.pathname.startsWith('/icons/') ||
req.nextUrl.pathname.startsWith('/fonts/')) {
return;
}
// igonring api/auth
if (req.nextUrl.pathname.startsWith('/api/auth')) {
return;
}
// user session
const session = await getToken({ req })
// redirecting to homepage if a logged in user tries to access the login page
if (req.nextUrl.pathname.startsWith('/auth/login')) {
if (session) {
const url = req.nextUrl.clone()
url.pathname = '/'
return NextResponse.redirect(url)
}
}
// // redirecting to login page if not logged in
if (!req.nextUrl.pathname.startsWith('/auth/login')) {
if (!session && session == null) {
const url = req.nextUrl.clone()
url.pathname = '/auth/login'
return NextResponse.redirect(url)
}
}
}
this works for general routes, but when I try to fetch some data in other pages from other API routes I get this error:
FetchError: invalid json response body at http://localhost:3000/auth/login reason: Unexpected token < in JSON at position 0
at E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\compiled\node-fetch\index.js:1:51227
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async getServerSideProps (webpack-internal:///./src/pages/departments-marking.js:70:22)
at async Object.renderToHTML (E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\server\render.js:490:20)
at async doRender (E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\server\base-server.js:908:38)
at async cacheEntry.responseCache.get.isManualRevalidate.isManualRevalidate (E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\server\base-server.js:1013:28)
at async E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\server\response-cache.js:69:36 {
type: 'invalid-json'
}
this error only occurs because of the middleware and if i remove the middle everything works but that means anyone can access the website and also post data to the server
The problem occurred because when I was trying to fetch data from an API route there was no cookie with the request headers, and !session && session == null would stop it because it showed as not authenticated, so I fixed it with adding user cookies with request headers while fetching the data, like this:
export async function getServerSideProps({ req }) {
try {
// fetching centers
const data = await fetch(`${server}/api/API-ROUTE`, {
method: 'GET',
headers: {
'cookie': req.headers.cookie, // this is where I parsed the cookies
'Content-Type': 'application/json',
'Accept': 'application/json'
},
}).then(res => res.json())
return {
props: {
data
}
}
}
catch (error) {
console.log(error.message)
return {
props: {}
}
}
}

Postman not sending request with `pm.sendRequest` if cookie jar is empty

Postman is not sending request with pm.sendRequest if cookie jar is empty.
I run a Test after every request in a collection, to check if the request was authorized. If not i get the necessary cookie and set it.
This works if the cookie is invalid but already exists in the cookie jar.
If the cookie does not exists already the code runs like expected but pm.sendRequest is not execute at all.
No log inside the request function in the console (i use logs to check if the code part is reached), no request visible in the console. But the other logs are still printed. Neither do i get an error.
The code:
if (pm.response.status == "Unauthorized") {
var domain = pm.environment.get("domain");
const jar = pm.cookies.jar();
jar.unset(domain, "session");
const postRequest = {
url: 'http://' + domain + ':5000/api/v1/oauth2/token',
method: 'POST',
header: {
'Content-Type': 'application/json',
},
body: {
mode: 'raw',
raw: JSON.stringify({
"identification": "admin",
"password": "admin"
})
}
};
console.log("before sending") //**guard one - reached every time**
pm.sendRequest(postRequest, (error, response) => {
console.log("sending") //**guard two - only reached if cookie exists but is invalid**
if (error) {
console.log("ERROR");
console.log(error);
}
else {
console.log("setting token via request")
let token = response.json().token;
jar.set(domain, "session", token, (err, cookie) => {
if (err) console.log(err);
else console.log("COOKIE:", cookie)
})
}
})
console.log("after sending") //**guard three - reached every time**
}

Migrate ADAL.js to MSAL.js

I have a SPA which uses the solution provided here to authenticate with Azure AD and everything works as expected. Now I want to migrate this to use MSAL.js.
I use below for login:
import * as MSAL from 'msal'
...
const config = {
auth: {
tenantId: '<mytenant>.com',
clientId: '<myclientid>',
redirectUri: <redirecturi>,
},
cache: {
cacheLocation: 'localStorage',
}
};
const tokenRequest = {
scopes: ["User.Read"]
};
export default {
userAgentApplication: null,
/**
* #return {Promise}
*/
initialize() {
let redirectUri = config.auth.redirectUri;
// create UserAgentApplication instance
this.userAgentApplication = new MSAL.UserAgentApplication(
config.auth.clientId,
'',
() => {
// callback for login redirect
},
{
redirectUri
}
);
// return promise
return new Promise((resolve, reject) => {
if (this.userAgentApplication.isCallback(window.location.hash) || window.self !== window.top) {
// redirect to the location specified in the url params.
}
else {
// try pull the user out of local storage
let user = this.userAgentApplication.getUser();
if (user) {
resolve();
}
else {
// no user at all - go sign in.
this.signIn();
}
}
});
},
signIn() {
this.userAgentApplication.loginRedirect(tokenRequest.scopes);
},
And then I use below to get the token:
getCachedToken() {
var token = this.userAgentApplication.acquireTokenSilent(tokenRequest.scopes);
return token;
}
isAuthenticated() {
// getCachedToken will only return a valid, non-expired token.
var user = this.userAgentApplication.getUser();
if (user) {
// get token
this.getCachedToken()
.then(token => {
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
// get current user email
axios
.get('<azureapi-endpoint>' + '/GetCurrentUserEmail')
.then(response => { })
.catch(err => { })
.finally(() => {
});
})
.catch(err => { })
.finally(() => { });
return true;
}
else {
return false;
}
},
}
but after login I get below error:
Access to XMLHttpRequest at 'https://login.windows.net/common/oauth2/authorize?response_type=code+id_token&redirect_uri=<encoded-stuff>' (redirected from '<my-azure-api-endpoint>') from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Also the token that I get seems to be invalid as I get 401 errors trying to call api using the token. Upon checking the token against https://jwt.io/ I get an invalid signature.
I really appreciate anyone's input as I've already spent good few days and haven't got anywhere yet.
I'm not sure if this is your issue. however, for msal.js, in the config, there is no tenantId parameter, it's supposed to be authority. Here is a sample for graph api using msal.js
https://github.com/Azure-Samples/active-directory-javascript-graphapi-v2
specifically: the config is here: https://github.com/Azure-Samples/active-directory-javascript-graphapi-v2/blob/quickstart/JavaScriptSPA/authConfig.js
as per here, https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications it is supposed to be hitting login.microsoftonline.com not login.windows.net

Upload Image from triggerio to express.js fails

I'm trying to post a file from a mobile triggerio app to a nodejs service. The request hits the post method, but the fails because the form object is null in the request obj.
(TypeError: Cannot call method 'complete' of undefined)
I've adapted the code from the accepted answer in this post : Uploading images using Node.js, Express, and Mongoose
This is my current nodejs code:
var express = require('express')
, form = require('connect-form');
var app = express.createServer(
form({ keepExtensions: true })
);
app.post('/fileupload', function(req, res, next){
//req. form is nulL
req.form.complete(function(err, fields, files){
if (err) {
next(err);
} else {
console.log('\nuploaded %s to %s'
, files.image.filename
, files.image.path);
res.redirect('back');
}
});
req.form.on('progress', function(bytesReceived, bytesExpected){
var percent = (bytesReceived / bytesExpected * 100) | 0;
process.stdout.write('Uploading: %' + percent + '\r');
});
});
app.listen(process.env.PORT);
console.log("express started");
And this is my upload method in triggerio:
function uploadFile (file){
forge.request.ajax({
url: 'http://resttrigger.aykarsi.c9.io/fileupload',
type: 'POST',
files: [file],
fileUploadMethod: 'raw',
dataType: 'json',
success: function (data) {
forge.logging.log("success " + data);
},
error: function (e) {
forge.logging.log("error " + e);
}
});
}
Using fileUploadMethod: 'raw' might be the problem here: it means that the request body is just a binary blob, rather than the multipart-encoded form which your node code expects.
For reference, here is a minimal handler that will save uploaded files into /tmp:
exports.upload = function(req, res){
var filename = '/tmp/' + new Date().getTime();
console.log(JSON.stringify(req.files));
// replace "test" with your actual form field name
fs.readFile(req.files["test"].path, function (err, data) {
fs.writeFile(filename, data, function (err) {
res.send({filename: filename});
});
});
};