how to hide nextjs api routes from being directly accessible through url? - javascript

Is there any way to make next.js API routes response data hidden when accessing it through URL? I want to hide the routes because there is some data I don't want to be directly accessed by the user.

Probably quick & simple way to protect the API routes is through the stateless session management libraries like iron-session with save / creation and destroy endpoints to validate and invalidate the Next JS api routes
Try this github example by Vercel. This might a be good starting point.
Remember: Always use a best authentication mechanism to protect any direct api route call with appropriate privileges in place. DYOR

There is no way to hide API routes from users through url in nextjs. In fact, nextjs API routes are publically available to anyone when you host the website without exporting and hosting from out folder. I ended making server-side routes using node express and then connected to the frontend in nextjs.

It is extremely unworthy effort to hide API routes. and for protecting essential data in API..there is CORS and Authentication methods can prevent noicy unwanted traffic I found brilliant blog on this
https://dev.to/a7u/how-to-protect-nextjs-api-routes-from-other-browsers-3838

You can set an authorization header that checks auth key everytime user access that API, that way normal user wont be able to access the page without knowing the auth key

In Next.js version 13 you can use middleware to stuck the user from directly checking the route of your api by checking the req.referer then only your app can call and api of your app. Auth token can also be use inside middleware.
https://nextjs.org/blog/next-13-1#nextjs-advanced-middleware
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(req: NextRequest) {
const url = req.nextUrl
const { pathname } = url
if (pathname.startsWith(`/api/`)) {
if (!req.headers.get("referer")?.includes(process.env.APP_URL as string)) {
return NextResponse.json({ message: 'Unauthorized' }, { status: 401 });
}
}
return NextResponse.next()
}
export const config = {
matcher: ['/((?!_next|fonts|examples|svg|[\\w-]+\\.\\w+).*)'],
}
process.env.APP_URL is the url of your app for example : http://localhost:3000

Related

Given a user's request for the index page ('/'), how do we intercept and run a function on the server in Next.js?

Is there a way using a middleware function or some other method in Next.js to see if a user is attempting to go to the home page?
What I'm trying to do basically is intercept a user's request for the home page. Intercepting a URL request is relatively easy to do with Next.js middleware. For example, if you want to see if a user is trying to access a single page called /login, you can access the request url like so:
export default async function middleware(req, res){
const url = req.url;
if (url.includes('/login')){
// carry out action
}
}
However, how can this be done for a home page URL (e.g https://fakewebsite.com/ or in development, localhost:3000)?
I think you can use the middleware introduced in nextjs version 12 to accomplish this. There you can introduce a config for matching URLs and have access to user's request:
Next.JS middleware.
The problem with what you have is that you're missing the config export from your middleware, inside which you can specify the matcher:
// middleware.js
export const config = {
matcher: '/',
}
This will only allow home requests to reach your middleware.

Storing API Keys in react-native app with expo library

I have a question, please, if possible explain in simple terms. Im new to react native, what's the best way to store API keys in a secure way where they can't reverse engineer it and get the keys right away. Can I just retrieve it from the server side using a restapi to get the apikey only if user is signed in? I'm trying to upload pictures to aws storage, but I want to store the APIKey somewhere where it's difficult to retrieve at least by hackers. Also, is there a way to send images trough the server express.js(from react native to express app) how can I do it, so I can upload it to aws storage or even if it is possible on mongodb instead of aws storage.
For example:
const express = require("express");
const requireAuth = require("../middlewares/requireAuth");
const router = express.Router();
router.use(requireAuth); //make sure they are signed in
/**
* * GET: Api key for the amazon s3 bucket storage
*/
router.get("/apikey/amazonstorage", (req, res) => {
const APIKEY = process.env.APIKEY;
if (APIKEY) {
res.status(200).send(APIKEY);
} else {
res.status(502).send(null);
}
});
Thank you in advance
In general, the safest way to handle API secret keys is to store them on your backend server and have the server make those requests to the third party APIs for the client (and send the results back to the client if necessary).
From the React Native docs:
If you must have an API key or a secret to access some resource from your app, the most secure way to handle this would be to build an orchestration layer between your app and the resource. This could be a serverless function (e.g. using AWS Lambda or Google Cloud Functions) which can forward the request with the required API key or secret. Secrets in server side code cannot be accessed by the API consumers the same way secrets in your app code can.

Nuxt.js Facebook Login appending '#_=_' to uri

I see plenty of others have had issues with facebook appending this to the callback uri and saw some good solutions for handling this client side with js embedded in the page. I have a nodejs api that handles the actual authorization with passportjs and passes it to our frontend (nuxtjs based on vue 2). The client stalls when trying to access/redirect any routes after being sent to the uri with the appended
I was hoping I could fix it with
//dashboard.vue
mount(){
if (window.location.hash == "#_=_"){
window.location.hash = ''
}
}
but this doesn't seem to fix anything with the router. I also tried adding a redirect to the vue router
//.nuxt/router.js
{ path: "/dashboard#_=_", redirect: "/dashboard" }
but the vue router dynamically generates on runtime so anything I hard-code there gets undone.
From what I undestand this is strictly a client side problem, but maybe I'm missing some parameter in the Facebook API call that could prevent this?
//backend api calling fb api
app.get('/facebook', passport.authenticate('facebook')) //not specifying scope since still in dev and haven't applied for approval

Share data between native app and mobile browser

I have a native application which installed on a client mobile device.
Other than that, I have a web application that this client can access via a mobile browser.
I would like to sync and pass information (such as identifiers or other user data) between the application and the web browser.
Is there any WebAPI that can help me do so?
I found the getInstalledRelatedApps that can indicate me whether my application installed or not, but what about sharing an information between those two? Is it possible somehow?
What frameworks are you using? Can I consider that you are using Node JS, React and React Native?
You could use express in the backend to create your own API, call it on the Frontend/Mobile with Axios, and then you could pass the parameters by setting them on the route. I.E. let's say that you want to pass on the tea ID from the mobile app to the web app so you can see them on your navigator:
// BACKEND
const express = require('express');
const routes = express.Router();
routes.get('/tea/:teaId', function (req, res) {
res.send(req.params);
});
module.exports = routes;
// MOBILE
import React from 'react';
import axios from 'axios';
import { Linking } from 'react-native';
const api = axios.create({
baseURL: 'http://your-url-here.com/',
});
let teaID = 22;
function sendToWeb() {
Linking.openURL(`https://your-url-here.com/tea/${teaID}`)
}
You can also pass Header Authorization in case that you want the user to be logged on and skip the login step or something related to it.
Express Routing
About Axios
I hope that this can help you a bit! And sorry if it seems confusing, it's my first time trying to answer a question!

Send headers with Vue-Router

I already searched for a good while on the Internet and even checked all suggested questions here, but I found nothing.
Basically, I'm using vue-router to load views when the user clicks on them (without prefetching, just lazy-loading), using a function that imports the Vue view/component. To better visualize, I made a barebone example of what I'm doing:
const router = new VueRouter({
routes: [
...
{
path: "/a_page",
component: function() {
return import("./views/A_Page.vue");
}
}
]
});
I'm using Express in the backend to protect certain routes, because protecting it in the Frontend is wasted effort, since the user could bypass the 'protection' easily, if he wants to. Also all views have their own splitted .js file (using "webpackChunkName") and Express needs a Bearer Authentication Token header for every API call OR .js file requested. This works great with Axios (responsible for fetching API data) where you can manually define a header, but vue-router hasn't this option, and since it doesn't send the Authorization header, it doesn't authenticate, Express blocks the file with a 403 and vue-router fails to import the file.
Is there any way to send the Authorization header with the import (which is basically just a GET request)?
Thanks in advance.
If someone thinks I'm approaching the problem in a wrong way, feel free to comment and suggest another way.
EDIT: The suggested duplicate question was given too little attention and the only solution given (which is basically split in 2) doesn't work with the current webpack anymore; onload(event) and onerror(event) get undefined.
You could use a router guard instead of protecting with basic auth.
I use this method, along with lazy loaded routes. If the auth fails you can redirect the user to a login page.
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
If (auth) { // get value of cookie etc for a jwt token or similar auth method
next() // proceed
}
else {
next(false) // cancel navigation
// or
next(“/login-url”) // redirect you login url
}
})
Additionally, you could use an axios method to auth on each route change.
If you want to send up the Authorization header (which doesn't seem to be an easy task, given that no one knows how to go about it...) I think you could override webpack's jsonp function that it uses to load the chunks in splitChunks...
Here's the docs for the webpack function that loads the chunks
You'll override your webpack config with your modified chunk loading function and then tie that into your vue.config.js like so...
// vue.config.js
module.exports = {
configureWebpack: require('./webpack.config.js')
}
All this being said, I would suggest protecting your frontend assets much earlier than when you need to be loading your split chunks and not requiring the Authorization header to serve your static assets.
Sometimes you can do this at the network layer (load balancer, etc) depending on your use-case. Other times using a server-based approach, like rendering your app w/ Nuxt, will be what you want.
If I'm understanding correctly (feel free to correct me), would you be able to do an auth call with axios prior to the actual routing, or perhaps upon the routing using a mounted call? Especially if there is no valid authentication you can then either redirect to a login page or re-route to an error page.
Feel free to let me know if I'm misunderstanding.

Categories