Hi everyone,
I just begun to use nuxt and is not clear to me what part of the code is shared between client and server and what part belong to each side exclusively. So i'm afraid to put some sensitive data like API credentials and things like that in code cause i dont know where this data will be readable only by server. Can someone help me to organize my code in some way that i can guarantee that the sensitive data will be only readable by server and not exposing on client inside some bundle javascript client side code.
Hi renatomattos2912;
I have just begun, too. I have the same concerns with you and i try to find out this.
I use this scenario: I try to crypt some data at server side with the secret key and send data to page.
In vue page's "fetch" property , i crypted the data and try to show in page like :
<template>
<div>{{ cryptedData }}<div>
</template>
<script>
export default {
async fetch () {
const myVar=myCryptoFunction('to be crypted variable')
return { cryptedData: myVar }
}
}
When i browse the page and view the source (ctrl+shift+F in Chrome and searched the secret key), i could see the secret key and my private crypto function! Also, i tried 'page middleware' but same problem occured...
Which way we should use for securing our data or private functions on server side?
I would like to know this too. I need to include some API keys but only on the backend.
Extremely good question, does nuxt not have an answer for this ? im facing same problem
From what I've gathered you should be fine when using environment variables that you access via process.env
, as long as you don't add them to the env
section of your nuxt config.
Be careful though if you plan to use .env
files with the dotenv nuxt module instead of using the dotenv package directly: by default the module will add each variable declared inside that file to options.env, thus exposing it to the client.
@mootari thanks, i'm using the dotenv nuxt module, i will try to change.
@mootari , as far as i can see from Nuxt, you cannot have code which is just on the backend and not exposed to the client, unless im mistaken, so even if you retrieve the keys from process.env, they will be in the client side code, for example if your making an axios request when a button is pressed;
//click event
{
const credentials = {accessKeyId: process.env.acccessKey};
}
//Then do something with the above credentials
If you need to fetch data using that key then you'll have to proxy that through a custom API endpoint. In the examples this is commonly done by running a small express server alongside nuxt.
Regarding unbundled code that interacts with nuxt directly: there's e.g. serverMiddleware, and afaik nuxt.config.js doesn't get bundled either.
Thanks @mootari, i will do some tests
Is it outside the scope of Nuxt for a feature like this?
I've been using a separate Express server alongside of Nuxt to accomplish things like this before, but having that functionality built into Nuxt would be fantastic.
Specifically, I want to be able to consume APIs which need keys without using a separate Express app to handle it.
I'm deploying a static site using the npm run generate
command. I have an .env file with the API key inside. I was previously using the @nuxtjs/dotenv module but as others have said this bundles up the api tokens and exposes them in the app.js client side file, I could see them in plain text.
To solve this I removed @nuxtjs/dotenv
and instead simply ran npm install dotenv
from https://github.com/motdotla/dotenv then at the top of nuxt.config.js add:
require('dotenv').config()
Then I just access all the .env variables using process.env.API_KEY etc. you can access them in nuxt.config.js and all pages.
I've checked all the js bundles etc and can no longer find the secret API key.
Hai @willbrowningme
I'v tested it did not work.... I still can see API_KEY on main.js on plain text
@willbrowningme Mind sharing your code? I don't see how that will work as once the Nuxt app is loaded in the browser, it effectively becomes a Vue app, no longer doing any server side stuff. Your API calls will still be processed by the browser after the first visit to your site. Yes, the first page load will be hidden from the user as it's processed on the server, but subsequent calls will be visible by the browser. At that point, you can sniff out those API keys with dev tools.
it's just working on server side but not client side
for whom using Firebase/Firestore realtime database will not working... for firebase that found solution is restricted credentials on cloud console
@Imanullah @krestaino The static site I've built only makes API calls on the server side using the asyncData method. Example source code can be seen here - https://github.com/willbrowningme/nuxt-cockpit-static-blog
If you're building an SPA that makes client side API calls then you might need to use a different way for authenticating calls.
so iv actually found a way around this. Not the prettiest solution but still works. Have your API credentials and your API call in a server middleware file (not exposed to client at all). Then from your front end where you want to make the API call, you then ONLY call the server middleware API, which will then in turn call the API you want to call, get the data and then return it to the browser.. Hope that makes sense
really hope nuxt can support such a basic requirement as a SSR framework.
can we have function like getInitialProps()
of next.js, it does:
req
, res
that is the reason we need SSR.
I'm specifically looking to have two pages:
Currently, the Auth Routes example can be easily bypassed by editing the store on the client side. The server doesn't actually protect the data on the server side, and sends the whole secret.vue
page to the client despite claiming not to do so.
Is there a way to protect whole pages or components from the server side?
why would you ever want to have a page or component "secret" and never sent to a users browser ? this would seem to defeat the whole point of developing a website / webapp ?
Hi all!
Actually, it's very easy to add some data in server side when fetching api.
You have to use the axios module with proxy one.
See the documentation : https://axios.nuxtjs.org/options.html#proxy
An example of configuration I have:
{
axios: {
prefix: '/api/',
proxy: true,
},
proxy: {
'/api': {
target: apiUrl,
pathRewrite: { '^/api/': '' },
headers: { 'X-API-KEY': apiKey },
logLevel: 'debug',
},
}
I let you read the available docs to understand all of that. 馃槈
yup, seems pretty much the same as the solution i coded. It sends an api request to a url which will return the protected API keys and then makes a concurrent API request with the results (keys) of the previous one
Outch, nope, it's not the same at all 馃槄 Here, only one call is made, just all calls are proxyfied. It's a native feature of nuxt.
In my solution, only one call is made from the client. And the serverMiddleware file is effectively the proxy..
@rosea1 If you look at the linked example, pages/secret.vue
is a page that is only supposed to be seen if the user has authenticated. The example is called "Auth Routes" (implying authentication is needed for those routes) but the whole pages/secret.vue
is sent to the client regardless of the user being authenticated.
To clarify, the component shouldn't be sent to the client unless the client is authenticated, which is not the case in the example.
Currently:
index.vue
secret.vue
secret.vue
is sent to the unauthenticated usersecret.vue
"denies access" and the page isn't displayed to the userDesired:
index.vue
secret.vue
secret.vue
)@malonehedges did you find a solution for this. I鈥檓 seriously considering nuxt for my next project, but if I can鈥檛 do things like consume API endpoints without my keys being exposed, there鈥檚 not much point.
@modermo Check this out. It's what I'm using on my latest project. Basically, you just use the express server to proxy the API calls, and from Nuxt, you make the API calls to the express server. It's quite easy to setup and pretty straightforward.
Awesome. Thanks, I'll check that out.
To make sensitive private data really private you can use builtin serverMiddleware, even without expressjs, it's very simple:
serverMiddleware: [
{ path: '/api', handler: '~/api/index.js' },
]
var querystring = require('querystring');
module.exports = function (req, res, next) {
if (req.method == 'POST') {
//For receiving POST requests
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end', function () {
var bodyParams = querystring.parse(body) || {};
console.log(bodyParams);
//ECHO POST params for example
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(bodyParams));
return false;
});
} else {
//For receiving GET requests
console.log(req.originalUrl);
var url = (req.originalUrl || '');
//ECHO url for example
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({url: url}));
return false;
}
}
asyncData
& fetch
are executed server-side anyway, so why can't we have middleware targetting server-side only in pages?
without these packages compiled into client.js
using lokijs with vue pages would be nice, so server-side handles rendering and database, without the massive overhead of using axios and making a whole api-server..
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
asyncData
&fetch
are executed server-side anyway, so why can't we have middleware targetting server-side only in pages?
@nitwhiz I believe that the serverMiddleware bits referenced by @bitk0der should do the trick:
https://nuxtjs.org/api/configuration-servermiddleware#the-servermiddleware-property
Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:
Issues that are labeled as 馃晲Pending
will not be automatically marked as stale.
Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:
Issues that are labeled as 馃晲Pending
will not be automatically marked as stale.
Hmm... so if I have in my store actions,
async nuxtServerInit () {
const secret = process.env.secret
data = await this.$axios.post(... {secret})
...
}
Will secret be somehow available in the client? (process is not, and secret
is not present in context.env
) If not, then this seems simpler than serverMiddleware?
Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:
Issues that are labeled as 馃晲Pending
will not be automatically marked as stale.
after using nuxt
for one year time, I found out the solution. there is no easy way to protect secret data, but express API.
GET /apis/secret
asyncData: async function ({req, res}){
const data = await axios(`/apis/secret/${somekey}`)
return {secret: data.data.secret}
}
It is impossible to wrap serverside code (Nodejs only) inside asyncData
, such as 'fs', 'os' modules. As the reason that asyncData
is also compiled through webpack
into browser javascript.
Possibly a helpful gotcha: any files added to the ~/middleware
folder will automatically be compiled into the client bundle, even if they aren't referenced the ~/nuxt.config.js
router.middleware
array.
This caught me off guard because I was trying to place both route middlewares and server middlewares in the same ~/middleware
folder for organization.
To remedy, I have moved server middlewares to a sibling ~/middleware-serverside
folder and they are no longer included in the client bundle.
after using
nuxt
for one year time, I found out the solution. there is no easy way to protect secret data, but express API.
@wahengchang I have had good success using server middleware, which are significantly less complex than defining a custom express API. See above note for gotcha.
server middleware leads to a mess, I will never use it again.
While this discussion emerges, I leave a small related blog post here 馃槈
https://blog.lichter.io/posts/my-take-on-using-nuxt-with-an-api/
Indeed, your article covers all the available approaches, including the one I like to use, for Nuxt + a REST API. @manniL
I read that article (and every single word you you wrote on your useful blog)
And Organize and decouple your API calls in Nuxt.js is also a very nice one.
Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:
Issues that are labeled as pending
will not be automatically marked as stale.
process.env values are only visible to the client if we set a variable that we're sending to the client, correct? Might be a silly question but after reading @rosea1 's comment, I just want to clarify. @rosea1 's comment was giving an example where process.env. was being set to a variable that was going to be available on client side, and not suggesting that in general all process.env values are exposed to the client..... right?... please say right
Hi all!
Actually, it's very easy to add some data in server side when fetching api.You have to use the axios module with proxy one.
See the documentation : https://axios.nuxtjs.org/options.html#proxy
An example of configuration I have:
{ axios: { prefix: '/api/', proxy: true, }, proxy: { '/api': { target: apiUrl, pathRewrite: { '^/api/': '' }, headers: { 'X-API-KEY': apiKey }, logLevel: 'debug', }, }
I let you read the available docs to understand all of that. 馃槈
I have the same problem, but I'm confused about @nuxtjs/proxy
how to import the apiKey
@mathieutu
I'm sorry but I'm afraid I don't understand your question. If you don't want to set it explicitly here, you're in a js file, what's the problem of importing a variable in it? Or (better) why don't you use an env var?
@youncccat The proxy configuration goes in the nuxt.config.js
.
// nuxt.config.js
module.exports = {
axios: {
prefix: '/api/',
proxy: true,
},
proxy: {
'/api': {
target: apiUrl,
pathRewrite: { '^/api/': '' },
headers: { 'X-API-KEY': apiKey },
logLevel: 'debug',
},
}
}
Then, you can use dotenv module to get API key from your .env
file which you do not check into your version control. Your nuxt.config.js
will end up looking something like this.
// nuxt.config.js with dotenv
require('dotenv').config()
module.exports = {
axios: {
prefix: '/api/',
proxy: true,
},
proxy: {
'/api': {
target: apiUrl,
pathRewrite: { '^/api/': '' },
headers: { 'X-API-KEY': process.env.SECRET_API_KEY },
logLevel: 'debug',
},
}
}
This works because:
.env
file is not committed to the repository. So it's not public.Hope that helps.
I'm a bit confused about setting proxy headers.
If i set my api-key in my proxy headers, so anyone which request my app through the proxy will get the data from my api ?
So if someone want to get the data from my api will use my app proxy to be authorize to access data ?
Most helpful comment
really hope nuxt can support such a basic requirement as a SSR framework.
can we have function like
getInitialProps()
of next.js, it does:req
,res
that is the reason we need SSR.