0

I'm trying to fetch data from the Middleware API and am using A secret key to Secure the API.

But when I try to fetch the data it just doesn't recognize the Secret params,

How can I make it fetch the data and make my secret key Secret.

.env.local

LOCAL_API_KEY=5b45f6898634abf9c3769b763c5fa8ddfc57d2cc943a0601f7bda4269ebe7342

updateUser.js

const {data: session} = useSession()
    useEffect(() => {
        if(session){
            const checkUserInfo = async() => {
                try{
                    const fetchUserInfo = await axios.get(`/api/users/${session.user?._id}`,{
                        params: {
                            API_ROUTE_SECRET: process.env.LOCAL_API_KEY
                        }
                    })
                    console.log(fetchUserInfo) //  Output: Code 401
                    delete fetchUserInfo.data.user.password 
                    delete fetchUserInfo.data.user.admin
                    fetchUserInfo.data.user && localStorage.setItem('userSession', JSON.stringify(fetchUserInfo.data.user))
                }catch(err){ 
                    console.log(err)
                }
            }
            checkUserInfo()  
        }else{
            localStorage.removeItem('userSession')
        }
    }, [session])

[id].js

import db from "@/database/connect"
import Users from "@/database/modals/users"

export default async function handler(req, res){
    const {id, API_ROUTE_SECRET} = req.query
    console.log('key', API_ROUTE_SECRET) // Output: undefiend
    if(API_ROUTE_SECRET !== process.env.LOCAL_API_KEY){
        res.status(401).json({error: 'Unauthorized User..'})
    }

    if(req.method === 'GET'){
        try{
            await db.connect()
            const userInfo = await Users.findById(id)
            await db.disconnect()
            if(userInfo){
                res.status(201).json({user: userInfo})
            }else{
                res.status(404).json({error: 'User not found'})
            }   
        }catch(err){
            res.status(404).json({error: 'No Data For This User'})
        }
    }else{
        res.status(500).json({error: 'ONLY GET REQUESTS ARE ALLOWED'})
    }
}
Viper
  • 29
  • 7
  • Check this: https://stackoverflow.com/questions/61038365/nodejs-not-recognizing-env-file – DexieTheSheep Mar 25 '23 at 04:41
  • How are you loading in the env file? – Evert Mar 25 '23 at 04:46
  • @Evert Wdym loading the file, it's automatically implemented from Node.js – Viper Mar 25 '23 at 04:51
  • @Viper no, loading `.env.local` is _not_ a Node.js feature. Usually packages such as `dotenv` do this. `process.env` _is_ a Node.js feature, but that uses real environment variables. Libraries such as `dotenv` read `.env` files and turn them into real environment variables. But if you don't use a library like that, it doesn't happen. – Evert Mar 25 '23 at 04:52
  • Did you solve your problem? I think your real question is : How to use env vars in react? – JRichardsz Mar 25 '23 at 05:23

2 Answers2

2

axios.get accepts a request config as the second parameter (not query string params).

You can use the params config option to set query string params as follows:

const fetchUserInfo = await axios.get(`/api/users/${session.user?._id}`, {
  params: {
    API_ROUTE_SECRET: process.env.LOCAL_API_KEY,
  },
});
0

WARNING:

Do not store any secrets (such as private API keys) in your React app!

Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.

Solution

Prefix your env variables with REACT_

REACT_LOCAL_API_KEY=*****

and the use it with

process.env.REACT_LOCAL_API_KEY

CSR SPA variables

No matter if you are working with react, vue o angular, the problem is the same: CSR applications are just javascript loaded in the browser, so for security reasons, the javascript cannot read env variables of the user machine.

Only server applications are allowed to read env variables of machine.

Build vs Runtime

By default, in all the well known frameworks (react, vue o angular) variables are hardcoded on any build, not at runtime. So if you want to have several stages(test, uat, prod, etc) you will need to build for each stage.

At runtime (web browser, not your development IDE) , your js application only plays with global variables which are an emulation of the env variables inserted at build time:

enter image description here

process.env.FOO

process.env are the only option to read env variables at server layer.

Some frameworks like react , creates an emulation of this and expose it as global var to be easy the usage:

enter image description here

But since this is an emulation, to avoid the expose of all the environment variables (build or developer machine), react will only expose variables prefixed with: REACT_

enter image description here

Just one build

If you understood the complications of to build for each stage, instead just one build like server applications, you could use my strategy:

https://jrichardsz.github.io/devops/just-one-build-for-spas

Basically, you should expose a /settings in the server which is serving your frontend (react, angular , vue).

Then instead to use the framework options

  • React: process.env.REACT-FOO
  • Angular: ../environments/environment

Consume the /settings and the result expose it as global variables.

With this you will have one frontend build capable to be deployed on any stage because it don't have hardcoded values at build time

You could use my spa server which offer this feature:

https://github.com/usil/nodeboot-spa-server

JRichardsz
  • 14,356
  • 6
  • 59
  • 94