Using React to restrict/allow resource based on client ip address - javascript

I'm building a react app and want to allow/deny access to some components based (mainly filter IP||MAC) on where the client is.
Any way to restrict routing to deny access to a presentation when the client is connecting from the internet allowing the access when it connects via LAN?
I think I found an alternative approach, I will maintain the question open looking for alternatives.
I read that the client should not be able to see its ip address (browser security), and that should be done on the server side (thats a direct approach as mentioned in the above post) (can anyone confirm that).
The solution is to find the gateway address of the client (normally using NAT) and compare with my gateway address, if equal they are inside LAN.
I am having a situation that on the computer I am able to see the ip address, on mobile/cellphone I can't, need to investigate.
import React from 'react';
export default () => {
const [addrObj, setAddrObj] = React.useState({});
const fetchAddrData = async () =>
await fetch('http://jsonip.com')
.then(res => res.json())
.then(setAddrObj);
React.useEffect(() => {fetchAddrData()},[])
return (
<>
<h3>Sample Page</h3>
<h4>addr: {addrObj.ip}</h4>
</>
)
}

From what I've just read, JS alone can't retrieve the IP address. You might want to store it to a JS variable in the <head> with PHP, like
<?php echo '<script>var ip = '.$_SERVER['REMOTE_ADDR'].'</script>' ?>
This way the IP address is available to your JS.
And this post can help you track the location, even though you might want to use PHP for that as well.
How to get client's IP address using JavaScript?
And if you really don't want to use PHP, than this article uses jQuery. It does a request though. I'm not sure how important performance is to you.
https://www.geeksforgeeks.org/how-to-get-client-ip-address-using-javascript/
How to get client's IP address using JavaScript?

Related

Allow admin panel of react-firebase web app to only specific IP addresses?

I want the page of website (e.g."https:// website-URL/admin") only accessible specific IP addresses.
I use firebase.google.com & Vercel.com etc. for hosting commonly along with NodeJS & React JS for backend.
Firebase hosting is delivered through Fastly, when using cloud functions for onCall and onRequest, you can access this from the header fastly-client-ip
Otherwise, if it is from the client, you can call a Cloud Function to check it, or do a remote check with a service, but these kinds of checks are purely cosmetic and can be bypassed if someone created a script to override it.
import publicIp from "public-ip";
export const getClientIp = async () => await publicIp.v4({
fallbackUrls: [ "https://ifconfig.co/ip" ]
});
npm package: https://www.npmjs.com/package/public-ip
beyond the above options, this feature is limited and not accessible to you directly within Firebase config.

Authenticate requests from frontend that doesn't have tokens

Not sure if the title summarises my question well.
Basically, I am trying to authenticate routes such as checking if user exists etc. I only want to allow
requests coming from my frontend application to be approved, but, since no user is signed in there is no token to send.
Api request -
mywebiste/checkUser/email
This route is unprotected on my backend because no user is logged in.
BUT I want to protect this route, in such a way that it's accessible only from the frontend.
Some ideas I came up with were adding specific headers tag from the frontend and check them on the backend, but that could be easily replicated, is there something more secure like using tokens etc.
I am using React and Node.js
Same origin policy is going to give you some basic protection, but basically if an API endpoint is exposed publicly, it's exposed publicly. If you don't want that route to be publicly accessible you need to add access control.
If you use that route to check if a user is already registered, you could, for example, merge it with the user registration route and send a different error code if the user already exists (which is not a great idea because it leaks which emails are registered on your system).
You can verify that a request was originated by a user (by authenticating him) but you cannot verify that a request comes from a particular client because of these two reasons :
If you include some API key in your client (web page or other), it's easily retrievable by everyone (the best thing you could do is offuscate it which makes things slightly harder but still possible)
If you send an API key over the network it's easily retrievable as well
The only thing you could do is prevent other web pages from calling your backend on behalf of the user, by using CORS (which is actually active by default if you dont specify an Access-Control-Allow-Origin header)
I ended up creating a kind of working solution, so basically, I create a new base64 string on my frontend and attach that to the header while making a request to the backend. The base64 string is different every minute, so even if the header is copied, it differs every minute and is combined with your secret key.
I have made a package so that people can use it if they want - https://github.com/dhiraj1site/ncrypter
You can use it like so
var ncrypter = require('ncrypter');
//use encode on your frontend with number of seconds and secret key
var encodedString = ncrypter.encrypt(2, 'mysecret1')
//use decode on your backend with same seconds and secret
var decodedString = ncrypter.decrypt(encodedString, 2, 'mysecret1');
console.log('permission granted -->', decodedString);

Only allow users on page if IP address is approved

How can I make an HTML (and CSS/PHP/JavaScript) document which only allows certain IP addresses on a page?
(I am not asking how to find IP address with PHP, but how to allow access to a page based on an IP address.)
put this on the top of your php file and update the allowedIps variable with the IPs that you want to allow.
$allowedIps = ['198.x.x.x', '200.x.x.x'];
$userIp = $_SERVER['REMOTE_ADDR'];
if (!in_array($userIp, $allowedIps)) {
exit('Unauthorized');
}
for non PHP files (eg .html, .css) you will have to update your .htaccess file to add file specific permission. The following SOF thread should help: (assuming you are using apache server)
.htaccess: how to restrict access to a single file by IP?
If you dont want to bother with the code, put your site on Cloudflare and block ips
Try this with PHP :
function CheckIPAccess() {
//allowed IP. Change it to the IP addresses you want to allow to access your webpage
$allowedip = '127.0.0.1';
$ip = $_SERVER['REMOTE_ADDR'];
return ($ip == $allowedip);
}
Usually, IP restrictions are done at the web-server configuration level, so that unauthorized IPs simply can't reach your code at all.
It would actually be quite messy to try to do this kind of check within your application – "you'd undoubtedly miss one" – but the server can easily do it for you.
(I do not recommend attempting to use IPs for privilege checking and so forth ... "IPs change. Frequently. Very messy. Very ...")
Even stronger yet would be firewalls, and maybe VPNs. You really want to keep intruders as far away as possible and to give them as little information as possible. (For instance, why should they even be able to detect that the web-server exists?) Strive to make the entire setup as "hardened" as possible.

Get an access token without being connected to facebook

I need to retrieve a facebook page's list of posts (feed) using their javascript SDK, just like they explain in their docs: https://developers.facebook.com/docs/graph-api/reference/v2.4/page/feed
/* make the API call */
FB.api(
"/{page-id}/posts",
function (response) {
if (response && !response.error) {
/* handle the result */
}
}
);
I need it to be my website's "news section", so users should see it even if they are not connected to facebook.
The problem
Cool, but there is a problem... It returns: An access token is required to request this resource.
Holy cow... I'd like to get some access token for you #facebook, but my app doesn't make use of your authentication tools/plugins.
ANYWAY, I tried with FB.getLoginStatus(); but doesn't work, because the only way it can return an access_token is if the user is actually connected to the application. My users may not even be logged to facebook!
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
I've already payed a look to this SO question, but it doesn't solves my problem, simply because there are no such "generic tokens".
I've also read https://developers.facebook.com/docs/facebook-login/access-tokens/ and that also relies on tokens generated through facebook login methods... So, can't I display a list of fb page's posts in my website, without being connected into facebook, hence an application?
ADD: My app is build with angularJS, I'm not dealing with server-side code. I shall rely purely on javascript methods.
You could either use an page or an app access token, but as you'd be using them on the client-side, neither of them are an option.
See
https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens
https://developers.facebook.com/docs/facebook-login/access-tokens#pagetokens
Note that because this request uses your app secret, it must never be made in client-side code or in an app binary that could be decompiled. It is important that your app secret is never shared with anyone. Therefore, this API call should only be made using server-side code.
I'd strongly recommend to build a simple server-side script (PHP for example) to proxy the request to the Graph API. You could then call this via AJAX for example and load the posts asynchronously (and alse get rid of the FB JS SDK!). There is NO way to handle this in a secure manner if you don't want to use FB Login for all of your users (which also doesn't make much sense IMHO).
I think it's straightforward :)
Since pages' posts are always public, it only needs a valid access token to retrieve page posts.
Quoting what you've written:
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
You only require an access token.
My suggestion would be;
- Generate an access token for yourself (no extra permission needed)
- request page-id/posts
This way you don't require other users to be connected to facebook, you can simply requests page-id/posts to retrieve posts with access token you generated for yourself.
I hope it solves your problem :D
TIP: As long as posts are public, you only require a valid access token, it doesn't need to be user or page specific.

How to get local IP address using JavaScript? [duplicate]

This question already has answers here:
Can You Get A Users Local LAN IP Address Via JavaScript?
(9 answers)
Closed 3 years ago.
I want to get local IP address of a client system. How can I achieve this using JavaScript ?
I don't think you can without some server interaction.
The easiest way would be making an AJAX request to a server-side snippet that, in PHP, would look like this:
<?php echo $_SERVER["REMOTE_ADDR"]; ?>
You can't directly. One approach could be to send an AJAX request to your server (if there is one), which can return the IP address from which the user is viewing the current page.
you probably need an external party that will tell you; even if it were possible to get the local ip from javascript (which I doubt) you will most of the time get private ip address in ranges 10.x.x.x or 192.168.x.x (or that other one which I just can't seem to remember)
So put the ip in the page by php, like suggested above, of have a dedicated script echoing just the remote ip. That will then be the ip you have as seen from on the internet.
I think, you can't. But if your server has at least Server Side includes (SSI) - which every apache installation has enabled by default - you can get the ip like this:
var ip = '<!--#echo var="REMOTE_ADDR"-->';
This works on my Mac when embedded in NodeJS code, and gives the local IP address of the server running the code:
// get local IP address - Command line used is: ipconfig getifaddr en0
const { spawnSync } = require( 'child_process' );
const ip = spawnSync( 'ipconfig', [ 'getifaddr', 'en0' ] );
// the two outputs generated:
console.log( `stderr: ${ip.stderr.toString()}` );
console.log( `stdout: ${ip.stdout.toString()}` );
// applied:
console.log( 'This JavaScript is running on: ' + ip.stdout.toString() );
Note: 'en0' is the network interface in this case - you may find that your network connection is through 'en1' or 'en2' etc, so you will need to add a bit of logic to find which interface is being used.
Hope this helps
Phil

Categories