I am new to server-side programming.
I am trying to serve a HTML file (mapview.html) after authentication ,but it does not appear without any error.
there is no problem with authentication process. I expect when I click on login button, the codes check req data
and after validating, mapview.html pop up but nothing happen.
res.sendFile() causes in jquery part, console.log(res), get me all html codes in console line of chrome.
files directory:
src
index.js
db
public
index.html
mapview.html
middleware
auth.js
routers
user
task
model
user
task
index.html
$('div[name="logIn"]').click( () => { // select a div element that its name is logIn
console.log('LOG-IN:')
$.ajax({
url: '/login',
data: $('#loginForm').serialize(), // Get email and pass from login form
type: 'POST',
success: function (res) {
console.log(res)
}
})
})
user.js
router.post('/login', async (req, res) => {
try {
const user = await User.findByCredentials(req.body.email, req.body.password)
const token = await user.generateAuthToken()
const publicDir = path.join(__dirname, '../public')
res.sendFile(path.join(publicDir + '/mapview.html'));
} catch (e) {
res.status(400).send(e)
}
})
index.js
const express = require('express');
require('./db/mongoose');
const bodyParser = require('body-parser');
const userRouter = require('./routers/user');
const taskRouter = require('./routers/task');
const app = express();
const port = process.env.PORT || 3000;
app.use(express.json()); // Parse recieved json body data from Postman
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/public'));
app.use(userRouter);
app.use(taskRouter);
app.listen(port, () => {
console.log('server is run on port:' + port)
});
when you are making the HTTP post request from index.html using ajax to verify user authentication details, on successful authentication you are sending a static html file which is simply a text response and will not be rendered as a web page (as you were expecting).
To solve this problem,
Create a separate route for accessing the mapview.html
app.get('/map', (req, res) => {
res.sendFile(__dirname + '/public' + '/mapview.html');
});
In your ajax response just redirect to the map route
$.ajax({
url: '/login',
data: $('#loginForm').serialize(), // Get email and pass from login form
type: 'POST',
success: function (res) {
console.log(res);
window.location.href = '/map'; // redirect to map route
}
});
I updated the codes and it looks like following code .
As I mention in the past comment , I need to authenticate before refirect through .href = '/map' and I do not know how to attach token to .href='/map.
we usually send token as header with ajax like this:
headers:{"Authorization": localStorage.getItem('token')}
in case I add it to .href ,something like this window.location.href = '/map + "?token=MY_TOKEN" , how can i get it in auth method?
user.js
router.post('/login', async (req, res) => {
try {
const user = await User.findByCredentials(req.body.email,
req.body.password)
const token = await user.generateAuthToken()
res.send({user, token})
} catch (e) {
res.send(e)
res.status(400).send(e)
}
})
router.get('/map', auth, (req, res) => {
const publicDir = path.join(__dirname, '../public')
res.sendFile(path.join(publicDir + '/mapview.html'));
});
index.html
$('div[name="logIn"]').click( () => {
$.ajax({
url: '/login',
data: $('#loginForm').serialize(),
type: 'POST',
success: function (res) {
localStorage.setItem('token', res.token);
window.location.href = '/map';
}
})
})
Related
I'm building a React-Node app to consume QuickBooks APIs using OAuth 2 authentication. The app is structured so that the react app runs off a dev server at localhost:3000, and proxies http requests to the express server at localhost:3001.
So, I'm having some trouble making API calls: the react component responsible for rendering API data is crashing, and I'm getting the following error
"Missing required parameter: access_token"
I have the following code in my express server, which converts the authorization code into an access token, and then (I think) passes that token to http://localhost:3000/companyInfo. However I suspect this is where the problem is - is the token actually being sent to this address, or have I misunderstood how OAuth works? Here's the server-side code in question:
app.get("/callback", function (req, res) {
oauthClient
.createToken(req.url)
.then(function (authResponse) {
oauth2_token_json = JSON.stringify(authResponse.getJson(), null, 2);
})
.catch(function (e) {
console.error(e);
});
res.redirect("http://localhost:3000/companyInfo" );
});
...here's my entire server:
const express = require("express");
const OAuthClient = require("intuit-oauth");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const port = process.env.PORT || 3001;
let urlencodedParser = bodyParser.urlencoded({ extended: true });
let oauth2_token_json = null;
let oauthClient = null;
app.get("/authUri", urlencodedParser, (req, res) => {
oauthClient = new OAuthClient({
clientId: "****",
clientSecret: "****",
environment: "sandbox",
redirectUri: "http://localhost:3001/callback",
});
let authUri = oauthClient.authorizeUri({
scope: [OAuthClient.scopes.Accounting],
state: "testState",
});
res.send(authUri);
});
app.get("/callback", function (req, res) {
oauthClient
.createToken(req.url)
.then(function (authResponse) {
oauth2_token_json = JSON.stringify(authResponse.getJson(), null, 2);
})
.catch(function (e) {
console.error(e);
});
res.redirect("http://localhost:3000/companyInfo" );
});
app.get("/getCompanyInfo", (req, res) => {
let companyID = oauthClient.getToken().realmId;
let url =
oauthClient.environment == "sandbox"
? OAuthClient.environment.sandbox
: OAuthClient.environment.production;
oauthClient
.makeApiCall({
url: url + "v3/company/" + companyID + "/companyinfo/" + companyID,
})
.then(function (authResponse) {
console.log(
"The response for API call is :" + JSON.stringify(authResponse)
);
res.send(JSON.parse(authResponse.text()));
})
.catch(function (e) {
console.error(e);
});
});
app.listen(port, () => {
console.log(`Server is listening on port: ${port}`);
});
...and here's the react component where I want to render the returned API call data:
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const CompanyInfo = () => {
const [ info, setInfo ] = useState('')
useEffect(() => {
axios.get('/getCompanyInfo')
.then(res => setInfo(res.data))
},[])
return(
<div>
<p> {info.CompanyInfo.CompanyName} </p>
</div>
)
}
export default CompanyInfo
The strange this is that sometimes I have been able to render the API call data in this component, but I can only do it once. If I refresh my page, it crashes, and I have to start the login process again in order to make the API call work.
i get a Cannot GET /api/auth/signup error every time i try to POST i cant figure it out why
can someone help me with this thanks very much i dont understand what im missing im tryning to post the register in the node js but it keeps telling me Cannot GET /api/auth/signup
auth.js
import axios from "axios";
const API_URL = "http://localhost:8080/api/auth/";
class AuthService {
async login(username, password) {
console.log(username, password);
return axios
.post(API_URL + "signin", {
username,
password,
})
.then((response) => {
if (response.data.accessToken) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
});
}
async logout() {
localStorage.removeItem("user");
}
async register(username, email, password) {
return axios.post(API_URL + "signup", {
username,
email,
password,
});
}
getCurrentUser() {
return JSON.parse(localStorage.getItem("user"));
}
}
export default new AuthService();
server.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
var corsOptions = {
origin: "http://localhost:8080",
};
app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// simple route
app.get("/", (req, res) => {
res.json({ message: "it works." });
});
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
It appears you are attempting to POST to a route that doesn't exist. You will need to build out your /api/auth/signup route in order to send a request to it from axios.
// simple example of post route
app.post("/api/auth/signup", (req, res) => {
const { username, email, password } = req.body;
// Your logic to register user in your database
// Send response after database interaction
res.status(201).json({ message: 'User signed up for service' })
});
For each Specific route you need to implement respective route in your application.
In your application, if you need to have access to two post request of different url, you need to handle two post route.
For`/api/auth/signin`
app.post('/api/auth/signin', (req, res)=>{
//Your Implementation here
res.status(201).json({message: 'Your Message'})
})
For`/api/auth/signup`
app.post('/api/auth/signup', (req, res)=>{
//Your Implementation here
res.status(201).json({message: 'Your Message'})
})
I am using node and express with vue. I try to implement a middleware for my node routes, to check the login token and if it is wrong, redirect to the login page.
This is my code so far.
Main app.js file
const express = require('express');
const path = require('path');
const cors = require('cors');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();
app.use(cors());
app.use(express.static(path.join(__dirname,'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use('/login', require('./routes/login'));
app.use('/performance', require('./routes/performance'));
const port = 4000;
http.createServer(app).listen(port, ()=>{
console.log('server runs on port ', port);
});
Then in my routes I have
const express = require('express');
const token = require('../../lib/token');
router.get('/:product/dataquality/', token.validate(), (req, res)=>{
const product = req.params.product;
db.dataquality(product)
.then((resolved)=>{
console.log('route dataquality result', resolved);
res.json({success:true, data:resolved});
})
.catch((error)=>{
console.log('route dataquality error', error);
res.json({success:false, data:false});
});
});
And this token.validate middleware is
const jwt = require('jsonwebtoken');
const config = require('../db/config');
const validate = ()=>{
return (req, res, next)=>{
const token = req.get('Authorization');
const key = config.key;
jwt.verify(token, key,function(err, decoded) {
if (err){
console.log('token error');
res.redirect('/login');
}
if (decoded){
console.log('token ok');
next();
}
});
}
}
exports.validate = validate;
This works fine and I see the token console logs when I login in my app. If I go to the browser and edit the token (delete a couple of characters, but not completely remove it) so the token is there but is the wrong token, it has the wrong value :
I see in my console token error and I get no data, but the redirect to login page never happens.
If I do res.redirect('http://localhost:8080/login'); I still get no redirect.
What am I missing? How can I fix this?
If you think this is a Vue issue, let me know, so I can provide Vue routing code.
Thanks
EDIT
This the file that handles routes in Vue - router.js
import Vue from 'vue'
import Router from 'vue-router'
import store from '#/components/store';
import Login from './components/Login.vue'
import Performance from './views/Performance.vue'
Vue.use(Router)
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: '/login',
name: 'login',
component: Login,
},
{
path: '/performance',
name: 'performance',
component: Performance,
beforeEnter: (to, from, next) => {
if (store.state.login.token == null || !store.state.login.token) {
next('/login');
}
else{next();}
}
},
{
path: '*',
redirect: '/login'
}
]
})
router.beforeEach((to, from, next) => {
store.dispatch('resetAccessToken');
if (to.fullPath === '/performance') {
if (!store.state.login.token) {
console.log('VUE route go to login');
next('/login');
}
}
if (to.fullPath === '/login') {
if (store.state.login.token) {
console.log('VUE route browse normally');
next('/performance');
}
}
next();
});
If I search for "route" in my browser console to find console.log('VUE route go to login'); or console.log('VUE route browse normally'); it says it found 160 but I cannot see none.
I still get no data, but I can browse normally to empty Vue pages. Node or Vue redirect should work and send me to login , but none works, so I still can browse around.
Thanks
I'm trying to make a simple POST request but I'm getting an empty response back from the server. I've sifted through all the SO questions regarding this topic and tried the solutions posted but to no avail.
I've tried changing the request header options to use 'application/x-www-form-urlencoded' and set bodyParser in my express app as app.use(bodyParser.urlencoded({ extended: true })); but that didn't work either.
auth-service.service.ts
login(loginInfo: object) {
return this.http.post<loginInfo>(this.loginUrl, { "test": "test" })
.pipe(
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.log('An error occured:', error.error.message);
} else {
console.log(`Backend returned code ${error.status}, ` +
`body was ${error.error}`);
}
return throwError('Something bad happened; please try again later.')
}
login.component.ts (calls the login service method)
onSubmit() {
const loginInfo = { username: this.username.value, password: this.password.value };
this.authService.login(loginInfo).subscribe(
resp => { console.log(resp); },
err => { console.log(err); }
)
}
server.js (I've defined routes here but they're not relevant)
const express = require('express');
const bodyParser = require('body-parser');
const api = require('./routes/api');
const app = express();
const port = process.env.port || 3000;
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
next();
})
app.use(bodyParser.json());
app.use('/api', api)
app.get('/', function (req, res) {
res.send(JSON.stringify('Hello from server'));
})
app.post('/login', (req, res) => {
let userData = req.body
res.send('Request body: ' + JSON.stringify(userData));
})
app.listen(port, function () {
console.log('Server running on localhost: ' + port);
});
I'm console logging the following:
Backend returned code undefined, body was undefined
Something bad happened; please try again later.
When I try using Postman, however, I get the response I expect (i.e. Request body: {})
I'm not sure as to why a response is retrieved when done through Postman but not when done through the app.
Any help is appreciated. Thanks!
You need to set body for POST request in auth-service.service.ts:
import { HttpParams } from '#angular/common/http';
login(loginInfo: object) {
const body = new HttpParams()
.set('test', 'test');
return this.http.post<loginInfo>(this.loginUrl, body)
.pipe(
catchError(this.handleError)
);
}
try using express.json its missing
app.use(express.json());
and
app.use(bodyParser.urlencoded({
extended: true
}));
In a universal app, i loose every users cookies on a server/server http request.
I have build a small nodeJS app that reproduce the thing:
const fetch = require('isomorphic-fetch');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const server = require('express')();
server.use(bodyParser());
server.use(cookieParser());
server.use(session({
secret: 'foo',
httpOnly: false
}));
server.get('/set-cookies', (req, res) => {
req.session.user = { name: 'john doe' };
res.send('OK');
});
server.get('/a', (req, res) => {
console.log('COOKIE IN A = ', req.cookies); // Cookies are here !
const options = { credentials: 'include' };
fetch('http://localhost:3131/b', options)
.then( () => {
res.send('OK');
});
});
server.get('/b', (req, res) => {
console.log('COOKIES IN B = ', req.cookies); // Cookies are lost ! How to get it back ?
res.sendStatus(200);
});
server.listen(3131);
1) Hit GET /set-cookies
2) Hit GET /a (the cookies are here as expected)
Issue: When the /a controller will make an AJAX request to GET /b, it won't transfer the cookies, so the the route /b is unable to authenticate the user
How to transfer the users cookies on every requests ?
I have heard about "cookie jar" but i couldn't explain clearly what it is, and i didn't find any clean explanation on the web, if someone could share some knowledges about that, it would be great !
whatwg-fetch has option to send cookies by the following, but it doesn't seem to work.
fetch('http://localhost:3131/b', {
credentials: 'same-origin'
});
You can send manually cookie to the fetch by the following way.
server.get('/a', (req, res) => {
console.log('COOKIE IN A = ', req.cookies); // Cookies are here !
const options = {
'headers' : {
'Cookie': req.headers.cookie
}
};
fetch('http://localhost:3131/b', options)
.then( () => {
res.send('OK');
});
});