I'm currently searching the best way for developing my next webapplication. I'm thinking about using Backbone.js and build a single page application. But I really can't imagine how to secure my app since nearly everything is done on client side. Of course I just could prevent the users from accessing my RESTful Api so they would not have access to my data. But all the view/model/collection/template js files are still accessible.
Or is there a known way to serve the js files with php (laravel), which would allow me to only serve the files I need for the respective user.
I just couldn't find a solution by searching the Web. But I just don't think that I am the lonely person who needs a clean and secure authentication method including different user rights.
Thank you in advance!
Your backend application will fetch data from a backend (= API), and probably send back some changes.
This code can't have "security holes / leaks" as long as your backend is secured.
If you are afraid of people stealing your code, you can always minify the JS (check grunt.js and almond.js for this)
To secure your backend you can make use of Laravel's auth class, and the auth filter as mentioned before.
Besides normal auth, you could implement roles, that you can assign to specific users, giving them more or less access to certain resources in your backend.
Here's the method I would try :
Separate the application in two parts.
One part - login via regular Laravel Auth on a separate page, and then when the user is logged in serve the single page app in a different view.
Wouldn't this work?
Web Services are no different than any other web application you build. At the end of the day you are exposing functionality to the client (which is also the attacker). It doesn't matter what the client is implemented in, if you expose dangerous functionality you will be hacked.
Have a session state, keep track of the user id and make sure that the user is only accessing resources they have been allowed to access.
I do not think that what JS/template files are exposed really matters. Essentially, you should only be allowing data interaction to authenticated users. Think of this as two separate applications.
The front-end application logs in, and a cookie is stored (or some other persistence is used).
The back-end application then uses the persistent authentication to validate every single user request for data, and every user action.
This way you don't have to worry about the security, the client can only fetch the data that the server allows it to, and, likewise, it can only interact with the data insofar as the server allows it. You shouldn't be relying on the client side for security anyway, even logged in, otherwise some malicious user could, conceivably, save all your frontend code and use it against you without authentication.
Related
The gist of it all is that I'm trying to fetch audio metadata from a user's google drive files to store them into firebase.
At first I intended to do this locally, entirely client-sided, because my front-facing web/iOS/Android app is in flutter;
but as it turns out, there's almost no library handling audio metadata properly, and after dabbling with it, I realized I could probably get some formats (say, .wav & most RIFF-type audio files) to work, but doing an entire library to handle all kinds of audio metadata was a task significantly bigger than my original plans. Another option would be to create interfaces between C++ code and/or JS code into my Flutter application, but I'd have almost no control over that, it's not the easiest of process, and there would be possible inconsistencies between platforms.
I might make that library eventually, but in order to facilitate my work, I decided to use a server as a middleman that'd run with node and handle the file requests and metadata treatment, & also facilitate the interactions with firebase for me by making them handled by a service account.
Now, this makes me run into one issue : how to handle the google Auth.
When my user logs into my app, I get all the required auth scopes (google drive files access and write, contacts, email, etc) for my app; it goes through the consent screen and I get authenticated.
I'm still a little confused with the recommendations from google and best practices in this case, since my app, in itself, did not require an auth system outside of getting access to the google drive files through google identification, and I therefore do not have Firebase/Firestore users; I can simply store them in my (firestore) database for identification purposes (or maybe tie in the frontend flow to my firestore app to also create a user when logging in through google if that is possible. I'm currently using the google sign in
flutter package.)
To come back to my actual problem now that the situation is laid out :
Should I just transfer the auth tokens (and maybe reverify them in some ways to avoid impersonation) from my frontend app to the server through a HTTPS post request or through headers, and use them to directly query the Google Drive API (I wouldn't even need to store them outside of memory, which would be relatively safe against any attacks on the server itself), handle the files and the possibly expired token ?
Should I modify my frontend workflow so it directly grants access to my server who would handle the session rather than getting the tokens locally ?
In the first case, I would most likely simply use the users UID as identifiers for the firestore data (none of it is sensitive anyway, it would simply be playlists and some metadata). In the second case, I could probably implement a stronger security on firestore using the firestore rules,but it'd require a significant amount of refactoring and logic changes in my frontend.
In case that wasn't clear, I wish my server to make all the Drive related requests (after getting the proper authorizations from the user of course) and handle these without having to request the files locally in frontend. Both solutions (and others if available) should work, but I'm wondering what the best practice would be in the context of the Oauth2 system used by google and the fact that the authorization is transitioning between client and server and could be subject to security issues.
I'll add code/visual representations if this isn't clear enough. It is to me, but I obviously designed the mess.
I am currently working on a web application. The client is designed in Vue.js and the server application is made with node.js and express.
As of now I plan to deploy both the client-website and the node.js-app on the same server. Both will be adressed via two different, unique domains. The server will be set up manually with nginx.
The problem now is that this solution won't prevent a user from being able to send requests to the server outside the client that was made for it. Someone will be able to call the /register route (with postman, curl etc.) to create an account an 'unofficial' way. I think the only clean solution is that only my Vue.js-app would be able to perform such actions. However, since both the server and the client are two different environments/applications, some sort of cross-origin-request mechanism (cors for instance) must be set up.
So I'm wondering, is this bad by design or is it usual that way? If I wanted this not to be possible, should I see to that issue and try to make the express-API as private as possible? If so, what are usual best practices for development and deployment / things to consider? Should I change my plan and work on a complete different architecture for my expectations instead / How do 'bigger' sites manage to allow no requests outside the official, public developer API's?
I think the only clean solution is that only my Vue.js-app would be able to perform such actions.
An API that is usable from a browser-based application is just open to the world. You cannot prevent use from other places. That just how the WWW works. You can require that a user in your system is authenticated and that auth credential is provided with each request (such as an auth cookie) before the API will provide any data. But, even then, any hacker can sign up for your system, take the auth credential and use your API for their own uses. You cannot prevent that.
If I wanted this not to be possible, should I see to that issue and try to make the express-API as private as possible?
There is no such thing as a private API that is used from a browser-based application. Nothing that runs in a browser is private.
If you were thinking of using CORs protections to limit the use of your API, that only limits it from other browser-based applications as CORs protections are enforced inside the browser. Any outside script using your API is not subject to CORs at all.
How do 'bigger' sites manage to allow no requests outside the official, public developer API's?
Bigger sites (such as Google) have APIs that require some sort of developer credential and that credential comes with particular usage rules (max number of requests over some time period, max data used, storage limits, etc...). These sites implement code in their API servers to verify that only an authorized client (one with the proper developer credential) is using the API and that the usage stays within the bounds that are afforded that developer credential. If not, the API will return some sort of 4xx or 5xx error.
Someone will be able to call the /register route (with postman, curl etc.) to create an account an 'unofficial' way.
Yes, this will likely be possible. Many sites nowadays use something like a captcha to require human intervention before a request to create an account can succeed. This can be successful at preventing entirely automated creation of accounts. But, it still doesn't stop some developer from manually creating an account, then grabbing that accounts credentials and using them with your API.
When talking about web applications, the only truly private APIs are APIs that are entirely within your server (one part of your server calling something in another part of your server). These private APIs can even be http requests, but they must either not be accessible to the outside world or they must require credentials that are never available to the outside world. Since they are not available to the outside world, they cannot be used from within a browser application.
OK, that was a lot of things you cannot do, what CAN you do?
First and foremost, an application design that keeps private APIs internal to the server (not sent from the client) is best. So, if you want to implement a piece of functionality that needs to call several APIs you would like to be private, then don't implement that functionality on the client. Implement that functionality on the server. Have the client make one request and get some data or HTML back that it can then display. Keep as much of the internals of the implementation of that feature on the server.
Second, you can require auth credentials for a user in your system for all API usage. While this won't prevent rouge usage, it will give you a bit more control because you can track usage, suspend user accounts when you find abuse, etc...
Third, you can implement usage rules for your public-facing APIs such as requests per minute, amount of data, etc... that your actual web application would never exceed so if they are exceeded, then it must be some unintended usage of the API. And, you could go further than that and detect usage patterns that do not happen in your client. For example, if you see an API user cycling through dozens of users, requesting all their profiles and you know that is something your regular client never does, you could detect that type of usage and block it.
Im planning on making an application that has two parts two it:
React native mobile app
Browser web-app for desktop users
I'm trying to plan out how im going to manage the backend authentication for this (Node.js, passport.js). Ideally, I can just have one backend manage it, regardless of which type of client.
Lets say im going to ONLY have google auth (for simplicity). I don't need to hit googles API's for any information (like profile, contacts, etc), I just want them to login with a google account. My understanding so far is that theres two main ways (especially since im using passport.js).
jwt based approach
session based approach
For either approach, my issue arises when it comes to the react native app. Since I'm not able to use the HttpOnly cookie, im not sure how to safely store data. e.g
In the jwt approach, if the server administers an access token and a refresh token, the react native client can just store them both in the same place e.g https://github.com/mcodex/react-native-sensitive-info. Which means the refresh token is just as susceptible as the access token, which defeats the point of a refresh token, so might as well just have the access token be long lived.
In the session based approach, react native can just store the session id some where (like react-native-sensitive-info above), and the same problem arises
My current thoughts on what should be done:
It seems like theres no way of getting around the security issue of storing information in react native, so as of now I feel like im just going to follow the JWT approach, and store the access + refresh token in react-native-sensitive-info. However, this does mean that the login endpoint is going to return the access + refresh token in the body of the request when the User-agent is mobile. When the user agent is web then we should be able to set an httponly cookie. The only thing that I can think of is if there is a malicious request that masks the user agent (is this possible?), and then can receive the access + refresh token in the body and will be able to do whatever with that.
Performance Aside
A session based storage approach seems much simpler overall. Yes it does store state on the backend, but if we did the JWT approach we would have to store peoples refresh tokens somewhere on the backend anyway (If theres ever a scenario where we need to invalidate peoples refresh tokens, e.g on logout or damage prevention).
This way, say we have a sessions table, when a user logs out, or if we want to invalidate sessions, all we have to do is delete rows from that table. In the JWT method, if we want to invalidate a refresh token, we have to have a blocklist table (which will only keep growing in size, since refresh tokens shouldn't expire, but I guess they can be dropped after a long period of time). However, if you have LOTS of users, the sessions table could get large, which could cause performance issues (but you could probably just drop sessions over a certain age)
/Aside
Questions:
Ive noticed mobile applications have NEVER asked me to relogin with OAuth. Does that mean they're constantly using their refresh token whenever the access token expires? If theres no clear way to store that in a secure way in mobile, do they just have super long lasting access tokens?
Is all of this thinking overkill? Is it fine to just store a super long-lasting access-token in react native and just use that all the time? Then when the user presses 'logout' we can drop that from local storage?
Would a third party auth system like auth0 manage all of this for me?
I'll try to share my experiencies in different kinds of app, this way things may get more clear.
Authentication Method
On most of the mobile applications (with web applications) I've worked with long term access tokens on the mobile side, most of applications don't require the user to login each time you open the app. Usually we store the token in a Secure Storage.
In some cases I've worked with a memory database (Redis) to put the user's session it's really fast and you don't need to query your main database each request (this was used for a high availability system, it may be overkill for most usecases)
Some very specific solutions may require more security, this will depend on your product (like banks, and transactions apps or apps the keep sensitive data) in these cases I would recommend you to login the user every time he closes the app or stays inactive for to long. (this kind of solution usually relies on fingerprint/faceId libs)
My personal opinion on this matter is to go with jwt, it's easy to maintain on the server side if you need to change backends and has a more defined pattern to follow, but that's my opinion and if you have high demand or some specific usecase this may change.
Storage
Talking about the storage options, there are some good suggestions on where to save data like tokens in a secure way on the react native docs,a good option I've used sometime would be:
https://github.com/emeraldsanto/react-native-encrypted-storage
but you can see more options and it advantages here:
https://reactnative.dev/docs/security#secure-storage
Third party libs
They usually helps with the basics if your projects has the budget and not a lot of customization on the authentication process, usually if it's a brand new project (on the back and front end) they work well.
Most of them will handle most of the hurdle for you like token renovation but you should mind the price scalability for these kind of approach
Wish success on your project.
I'm relatively new to the modern JavaScript web development world. I've built a very simple Node/Express back-end and a separate React front-end. My vague plan is to have users that will have permission to access certain areas of the front-end, and then have the front-end make requests to the back-end. Can the front-end and back-end share the same authentication/authorization scheme? Can they both use something like Auth0? How can I make these two secure?
I'm a little stuck and would appreciate any advice or a nudge in the right direction. I'm mostly stuck because these are two separate applications but the same "user" would technically have permissions to certain React views as well as certain Express endpoints - how they moosh together?
Thanks.
Although seems not directly related to your topic, but I would actually suggest you try Meteor if you are not planning to immediately start working on large projects (not pressing too hard on scalability).
Meteor has a builtin support for Accounts and interacts with MongoDB nicely, and it also has its own DDP protocol that simplifies API call massively. It also interacts nicely with React.
If you think Meteor might not be a good choice for yourself, you could still learn from its design policies of authorization, etc. It has quite a bit package source code that are not too difficult to understand, and should be helpful for you to learn the basic idea. (Actually, Meteor's Accounts package already implements the basic idea mentioned by another answerer, you can learn from its design principles)
When users log in to your site, issue them with an access token that they keep client side. On front-end, check if user has token and correct permissions before rendering components. On back-end, send the token as request headers to the endpoints.
I have implemented a similar case, but with the spring boot kotlin at the backend instead. My solution is using JWT token to validate the authentication and authorization.
User logins by input login form and send POST method to backend via a REST API.Backend validates credential and returns the JWT token including encrypted user_role, expiration date, etc... if valid or 403 exception
Front-end decodes the JWT (using jwt-decode lib or something else),
save it to validate the access permission to specific page in the
website based on user_role. Eg: role='ADMIN' can access to admin dashboard page, role='USER' can access user profile page, etc.
If you use express as the backend, I suggest to use the feathersjs. It has backend solutions for this and an optional front end version. Refer: https://docs.feathersjs.com/api/authentication/jwt.html
Secure Front end (React.js) and Back end (Node.js/Express Rest API) with Keycloak follow this
Let's say, there is a website for an online diary. Users upload their secrets to the web server and stored in the database. Normally, a user without the password can't see the diary items. However the web admin or DB admin could still can connect to the DB and see everything.
Is there a solution to prevent this? I mean a solution for the whole web application, not only for a single user.
Client-side javascript can encrypt the content, using a key known only to the client and never sent to the server, prior to saving.
However, the server can at any time start serving up malicious JS that would send the keys back down to the server. The only way to make this impossible is to make your application an installable client-side app (via an extension or whatever - but nothing that auto-updates). Additionally, all of this paranoia is pointless unless the user can verify what the app is doing, so it would need to be open-source.
At this point you're basically writing GnuPG, so you might as well just use that.