skip to Main Content

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'})
    }
}

2

Answers


  1. 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,
      },
    });
    
    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search