VueJS Secure with Auth0 - How is it secure? - javascript

I'm missing some sort of (most likely simple) fundamental understanding of securing a JavaScript application such as one using the VueJS framework and a service like Auth0 (or any other OAuth server/service).
1) If you create a SPA VueJS app with routes that require authentication, what stops a user from viewing your bundled code and seeing the views/templates behind that route without needing to login?
2) If you create a VueJS app that authenticates a user and sets some variable in a component like isLoggedIn = true or isAdminUser = true, what stops the user from manipulating the DOM and forcing these values to true?
All your JavaScript code is exposed to the client, so how is any of your code/content actually secure if it can be explored on the code level?

1) You understand correctly, nothing stops him. That's why you always do all that on the server side. The code in browser/VueJS is only to make the interface make sense, like hiding a button, but the server code should always do the actual check.
For example:
You have a button "Get secret document" that has a axios request behind to the path /api/sendsecret
In your VueJS app you can do something like v-if="user.isAdmin" to only show the button to the user.
There's nothing from stopping a user to find that path and just hit it manually with curl or postmaster or any other similar tool
Thats why the server code (nodeJS with express for example) should always do the checking:
app.get('api/sendsecret', (req, res) => {
if (req.user.isAdmin) {
res.send('the big secret')
} else {
res.sendStatus(401) // Unauthorized
}
})
2) Again, nothing. You should never authenticate a user in the VueJS application. Its ok to have some variables like isLoggedIn or isAdminUser to make the interface make sense but the server code should always to the actual authentication or authorization.
Another example. Lets say you're gonna save a blog post
axios.post('/api/save', {
title: 'My Blog Post'
userId: 'bergur'
}
The server should never, never read that userId and use that blindly. It should use the actual user on the request.
app.post('api/save', (req, res) => {
if (req.user.userId === 'bergur') {
database.saveBlogpost(req.body)
} else {
res.sendStatus(401)
}
})
Regarding your final marks:
All your JavaScript code is exposed to the client, so how is any of
your code/content actually secure if it can be explored on the code
level?
You are correct, its not secure. The client should have variables that help the UI make sense, but the server should never trust it and always check the actually user on the request. The client code should also never contain a password or a token (for example saving JSONWebToken in local storage).
Its always the server's job to check if the request is valid. You can see an example on the Auth0 website for NodeJS with Express.
https://auth0.com/docs/quickstart/backend/nodejs/01-authorization
// server.js
// This route doesn't need authentication
app.get('/api/public', function(req, res) {
res.json({
message: 'Hello from a public endpoint! You don\'t need to be authenticated to see this.'
});
});
// This route need authentication
app.get('/api/private', checkJwt, function(req, res) {
res.json({
message: 'Hello from a private endpoint! You need to be authenticated to see this.'
});
});
Notice the checkJwt on the private route. This is an express middleware that checks if the user access token on the request is valid.

Related

Server Side Routing vs. Front End Routing with Proxy

I hope my question doesn't come off as silly. I have quite a bit of experience on the front end but very little on the back end.
I have a React application which uses Node.js and Express on the back-end. I have declared "proxy": "http://localhost:3001" in my package.json which I am not 100% what this does but I know it is helping to connect my server (which runs on port 3001).
The issue I am having came about while setting up Auth0 on my backend to verify users. The first thing I noticed was that I was not able to run a get request to http://localhost:3001/login instead I had to navigate the user to the url http://localhost:3001/login. I'm not sure why this is but I assume it has something to do with Auth0 settings.
After I login Auth0 returns users to a callback url. Auth0's docs recommend using localhost:3000/callback since there docs also have a backend endpoint at /callback. However after logging in the user just gets routed to an empty page at http://localhost:3000/callback and the backend endpoint is never hit. I found that strange since I was basically copying and pasting from the Auth0 guide to setting up a login with Express.
Anyway I found that if I changed the callback url to my server at http://localhost:3001/callback than the server side code runs. This makes sense other than the Auth0 docs saying to use port 3000. It seems like maybe my proxy should be linking these somehow.
The callback endpoint function looks like this:
router.get('/callback', function (req, res, next) {
console.log('called')
passport.authenticate('auth0', function (err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.redirect('/login');
}
req.logIn(user, function (err) {
if (err) {
return next(err);
}
const returnTo = req.session.returnTo;
delete req.session.returnTo;
res.redirect(returnTo || '/user');
});
})(req, res, next);
});
When this runs successfully it should route the user to my Users page at localhost:3000/users however because I changed the callback route to 'localhost:3001/callbackthe callback endpoint is routing me tolocalhost:3001/users`.
I can kind of see what is going on. When I go to a url using 3001 I am hitting my endpoints. When I go to a url using 3000 I am viewing my front end pages. I just don't understand why the Auth0 docs would tell me to use my front end port for the callback?
I'll try to help but I'm not sure this is the answer.
If you set in your package.json the proxy to "proxy": "http://localhost:3001" then in your app to make a request you don't need to use the full URL,
axios.get('/login').then(res=>res.data).catch(err=>console.log(err));
For example without the proxy setted
axios.get('http://localhost:3001/login').then(res=>res.data).catch(err=>console.log(err));
In Auth0 the host URL and port is not a problem, U can use whatever U want, the point is the /callback route, in Auth0 you can configure a custom route for the callback but by default in your app, you need to have a route /callback. remember to add localhost:3001 to Auth0 configurations
I hope to help.

How does Express and React Routes work on initial GET request from browser?

I'm new to the react world and to the fullstack world as a whole but I've searched endlessly for an answer to the following and some guidance would be really appreciated.
I'm creating an app using React and Express. It requires authentication so I was planning on using Passport to help. The client side JS uses React Routers to navigate through the website. That's all fine but my issue is with the initial GET request made by the browser.
I'll first describe my specific app requirements and then generalize what I don't understand.
As I said, my application requires OAuth2 authentication. If you try to GET a path on my website and you're not logged in, it should just load the login page. If you are logged in, then load as normal and find your path. Similar to facebook, I'd like the login URL to be the same as the "feed" page. So similar to how facebook.com '/' route is either the login page or your new feed depending on whether you are signed in, I want the same thing.
From what I understand, Passport authenticates on the back end by checking the request header. So I understand that I should have some kind of middleware that says "if user is signed in, continue down the routes otherwise render sign in page" ... How is this done? What would the code look like? My only experience with Express was from an intro class which used res.render to send back an HTML file and pass it through some template engine like handlebars. But I have no idea how it'd work with react routes. Would i still use res.render()? Something else?
Let's say my index.html has the root div to inject the react into. If I had to guess, I'd send back that index.html page with the .js file with the routes and somehow on the backend send back the route I want it to match on my react routes (either the login one or the user requested)??
More generally, I guess I'm just confused how the initial request to a website using react routes is done. 1) How does the server interact with everything to render what I asked for? 2) What would the code look like for that. My only experience with React is from a basic Udemy course that just used "react-scripts start" to render the page.
After spending the entire day Googling this question it led me to SSR which is a rabbit-hole of its own and I'm not even sure if its what I need to help me. Is it?
I'm clearly missing some fundamental knowledge as this is really tripping me up so if you have any resources to learn more just post them. Thanks!
I understand your struggle as I've had to go through it myself when combining front-end with back-end, specifically React and Node. So first things first, we know that the browser/client will always initiate a request to the server, so how does React Router take control of the routes? Well its plain simple actually, all you have to do is return the entire react app from any route from your express server. The code will look something like this:
const express = require('express');
const app = express();
app.get('/*', (req, res, next) => {
// Return React App index.html
});
app.listen(3000);
Once the react app renders on the user browser (don't worry about paths, as react will automatically render according to the URL based on the code you wrote in the client side, it will also take care of authentication vs feed page when it will scan for your local storage, cookies, etc), it will take control of routing, instead of a request going to the express server. But what happens when we request data from our server, well it returns react app on each route so we need to setup an api route to handle any data requests.
app.get('/api/v1/*', (req, res, next) {
// Return some data in json format
});
Hopefully, this gives you insight about what you were looking for.
I think the fundamental gap you're struggling with stems from that lot of those 'intro courses' shove the entire browser client into the application server to get things up and running quickly, as in, the Node server renders the entire React app AND operates as an API...
// Ajax request from React app to: http://example.com/api
app.use('/api/*'),()=> {
res.send({ <!-- some JSON object -->})
})
// User visits in browser: http://example.com/**/*
app.use('/*',()=>{
res.render(<!-- entire React App sent to browser -->)
})
The first request (assuming the user doesn't visit /api/* ) will just send down the React bundle. Further user navigation within the client would generally send XHR requests (or open WebSockets) from the React app to Express routes running on the same node program.
In many situations it makes sense to have these parts of your program separated, as by having react delivered from a completely different location than where it requests data. There's many reasons for this, but optimizing computing resources to their differing demands of CPU, memory, network .etc and manageability of code/deployment are the big reasons for me.
For example...
User visits: http://example.com *
Nginx, Apache, a 'cloud proxy' .etc direct the traffic to a static React bundle, which has no authentication and never makes contact with your Node server.
If the user has Authenticate previously they will have token in local storage (if you're using JWTs for Authentication) and your React app will be configured to always check for these tokens when you first it is initially loaded.
If the user has a token it will send an Ajax request in the background with the token as a Header Bearer and will send back user data, then redirect them to an 'Authenticated page' like the FB feed you mention.
If they don't have a token or the token Authentication fails then React will redirect them to the Login or Registration page
React
React basically high jacks the browser's native 'location' functionality (whats displayed after you domain name). So any events after the initial page load (buttons clicks and such) are handled entirely by React internally and uses those routes to determine what to display or what data to fetch from the API through Ajax (XHR).
If the user performs a hard page reload then that request will go back to the server and it will perform the whole cycle over again
React Router
Allows you to do 2 things simultaneously...
Manipulate the browser Location and History objects.
Use that History and Location information elsewhere by detecting changes and sending off events.
SSR
I've only toyed around with SSR so I can speak to it, but its provides extremely low latency for initial renders, doing it in 1 network request, so you want to use it areas of your program where thats important.
Not sure if this answers you question, but let me know if you would like me to elaborate on anything or provide some more detailed resources.
SSR is a little bit confuses for developer that has less experience, let forget it for now.
It will be more easier for you to assume that frontend JavaScript (React) and backend Javascript (NodeJS) are two separate apps, and they communicate to each other via API.
here the code that show Login component and Feed component depending on whether you are signed in
import React, { Component } from "react";
import axios from "axios";
class Home extends Component {
constructor() {
const accessToken = localStorage.getItem("accessToken");
this.state = {
accessToken,
feeds: []
};
}
componentDidMount() {
if (this.state.accessToken) {
axios(`api/feeds?accessToken=${this.state.accessToken}`).then(({ data }) => {
this.setState({
feeds: data
});
});
}
}
render() {
if (this.state.accessToken) {
return <FeedsComponent feeds={this.state.feeds} />;
}
return <LoginComponent />;
}
}
and this is your backend
const express = require("express");
const app = express();
app.get('/api/feeds', (req, res, ) => {
const feeds = [
{},
{}
]
res.status(200).json(feeds);
});
app.listen(3001);
just keep in mind that they are two separate apps, the can be in two different folder, different server, different port.
Simply point Express to the folder containing your React files or build files.
app.use(express.static(__dirname + '/dist'));
where 'dist' contains the build files
See docs for more details

JWT deauthentication in React Redux App

I am having a tiny issue wrapping my head around how I would go about deauthenticating a user in the most efficient manner in my React/Redux application. (Using Redux Thunk as well).
Getting the token from the server is a piece of cake. Currently I:
- Send POST request with email and pw
- Receive Token back from server
- Save it to local storage.
Any additional requests after that to the server requires attaching the token inside an AUTHORIZATION header, which is fine.
Lets say that I walk away from the app after being logged in for awhile, then come back and decide to try to view another protected route. Lets call this route, "/latest-videos", which sends out an AJAX request to fetch the latest videos.
When that request is sent, the server determines that my token has expired, and will not allow me access to this resource. Obviously, this is where I would want to implement some type of action creator in Redux that will go ahead and redirect the user to the login page.
Do I need to perform some type of check on every AJAX request to see if the token has expired? It seems like doing that would require unnecessary boilerplate in every file that I have an AJAX request written.
This is where things get muddy for me. If we assume the token has a predetermined expiration date, how can I go about deauthenticating a user in the most efficient manner, without filling my app with poor code design choices?
You can assume I have a folder in my app called "actions" that contains files like so:
- actions
- videos.js
- users.js
- projects.js
- ...
Within a given file inside of the actions folder, you could have multiple Thunks that perform AJAX calls. Here is boilerplate example of what one of them may look like:
export function fetchVideos(query) {
return async (dispatch) => {
try {
dispatch({ type: FETCH_VIDEOS })
let res = await axios.post(`${API_URL}/videos/search`, {
query: query
})
// dispatch some success action creator with the data
}
catch(e) {
console.error('ERROR FETCHING VIDEOS: ' + e)
dispatch({ type: FETCH_VIDEOS_FAILED })
}
}
}
Hopefully I am making some sense...any help would be appreciated.
No need to check the token in your react app. Your server should be the one checking your token’s validity/expiry upon every request.
Since we’re talking about client application consuming restful api calls, server should be the one restricting the resources upon invalid token and return the 401 unauthorized response.
Upon that response, client app should deauthenticate a user and redirect to the login page (or send a request with a refresh token if you have any to avoid unnecessary login action).

Restricting url access by role in Parse Cloud Code

Is there any way to restrict access to a given url/route in a Parse CloudCode application?
app.get( '/', function ( req, res )
{
res.render('home');
} );
// only allow access to this 'route' if the user making the request is an admin
app.get('/admin', function(req, res)
{
var user = Parse.User.current();
// user is always null. No way to check their user privileges.
res.render('admin');
});
The problem as I see it, there is no way to access the Parse.User.current(), or request user in main.js file. Creating and then accessing an 'isAdmin' CloudCode function from the client seems the wrong way to prevent access by unauthorised users to urls.
Thanks in advance.
I couldn't comment on your post due to my low point. But have you tried on This documentation?
Your have to use parse made middleware for its express cloud : parseExpressCookieSession and parseExpressHttpsRedirect. Then you can access user data easily with Parse.User.current() in cloud code.
You can see the sample code on Parse SDK reference #parseExpressCookieSession
USER SESSION MANAGEMENT
You can add Parse.User authentication and session management to your
Express app using the parseExpressCookieSession middleware. You just
need to call Parse.User.logIn() in Cloud Code, and this middleware
will automatically manage the user session for you.
You can use a web form to ask for the user's login credentials, and
log in the user in Cloud Code when you receive data from this form.
After you call Parse.User.logIn(), this middleware will automatically
set a cookie in the user's browser. During subsequent HTTP requests
from the same browser, this middleware will use this cookie to
automatically set the current user in Cloud Code. This will make ACLs
work properly in Cloud Code, and allow you to retrieve the entire
current user object if needed.
...

Understanding how to use NodeJS to create a simple backend

I have been trying to develop a rather simple server in nodejs. Basically, what I am going for is a simple API that requires authentication (simple username/password style). What I do not need is any kind of frontend functionality (templating etc.). My problem is, I can't seem to get my head around the approach of express/node.
Specifically, my questions are:
How do I wire in the authentication? Do I pass several handlers into every route that requires authentication, or is there a more elegant way to do this?
How does the Express middleware (like app.use(express.bodyParser())) work? Do they alter contents of the request or response object? Specifically, if I use the body parser (internally formidable?), where do I access the request data this is supposed to parse?
When using authentication and I have, say, credentials stored in a database with more information about the individual client associated, at what point do I extract that information? I.e., when a user logs in, do I fetch the user record on login and pass it on, or do I fetch it in every handler that requires the information?
Ultimately, do you know of an open source application that I could take a look at? I'd like to see something that has simple authentication and maybe even utilizes formidable, since uploading a file is one of my requirements.
As I mentioned earlier, I believe my problem is ultimately a difficulty with the function-oriented approach in node (also, I have rather limited experience in webservice programming). If you know a resource where I could read up on how to approach architecting a nodejs app, please don't hesitate to point me to it.
How do I wire in the authentication? Do I pass several handlers into
every route that requires authentication, or is there a more elegant
way to do this?
You should use the session middleware. Here is some pseudo code:
var http = require('http');
var app = express();
var authorize = function(req, res, next) {
if(req.session && req.session.appname && req.session.appname === true) {
// redirect to login page
return;
}
next();
}
app.use(express.session());
app.all('/admin*', authorize, function(req, res, next) {
});
How does the Express middleware (like app.use(express.bodyParser()))
work? Do they alter contents of the request or response object?
Specifically, if I use the body parser (internally formidable?), where
do I access the request data this is supposed to parse?
Every middleware have an access to the request and response object. So, yes, it modifies it. Normally attach properties to it. This means that inside your handler (which is also a middleware) you may write:
if(req.body && req.body.formsubmitted && req.body.formsubmitted === 'yes') {
var data = {
title: req.body.title,
text: req.body.text,
type: req.body.type
}
// store the data
}
When using authentication and I have, say, credentials stored in a
database with more information about the individual client associated,
at what point do I extract that information? I.e., when a user logs
in, do I fetch the user record on login and pass it on, or do I fetch
it in every handler that requires the information?
I think that you should do the things the same way as in any other server side language. Keep the state of the user (logged/not-logged) inside a session. You may also keep the user's id and fetch the data for him whatever you need. It depends of your case, but you have the ability to cache information. Because node is not like PHP for example, I mean it's not dieing.
Ultimately, do you know of an open source application that I could
take a look at? I'd like to see something that has simple
authentication and maybe even utilizes formidable, since uploading a
file is one of my requirements.
Yep. I wrote an article about really simple MVC web site with admin panel. It is available here. And the code of it is here.
A simple way to implement authentication (if you don't want to use additional modules):
var checkAuth = function(req, res, next) {
if(!req.session.user)
{
// Redirect to login form
res.redirect("/login");
}
else
{
// Proceed to member's area
next();
}
};
app.get("/member/page", checkAuth, function(req, res) {
// render view, etc
});
bodyParser parses / converts the body of a POST request into an object, which helps with getting form submission values.
The route that handles your login form submission can access username / password like this:
var username = req.body.username;
var password = req.body.password;
At this point you'd query your database to select from users where the username and password matches (you'd want to use password encryption in a production environment).
If you get a record back in the query result, set it in the session. A simple way to do this is:
req.session.user = userRecord
(Adjust for your session middleware)
If you are looking for REST, I recommend using either Restify or booster
For authentication (distinct from authorization), use standard Basic, which can be handled by express.basicAuth() just to parse it and place it on the req object. Personally, I don't like basicAuth because it returns a 401 if there is no login, whereas the process of authenticating is different than determining if authentication is necessary.
For more advanced authentication, as well as session management, use cansecurity or passport. For authorization, you either can put individual middleware in each route, use cansecurity's middlewares, or use its declarative authorization.
Disclosure: I am the author of both booster and cansecurity.
If your goal is to build a RESTful API in Node.js, my best bet would be Restify, which uses a similar aproach of routes like Express, but eliminates all the high level stuff(templating, etc.) and ads backend functionalities(ie: body parser, ip blacklist, requests per hour).
For the authentication part, I would use another library perhaps, and wire it to a particular route. There are ORM's too that can solve your database needs(mongo and mysql are well supported, both for the "noSQL" fans and the classic db aproach ones).

Categories

Resources