I'm successfully working with environment variables in my local environment using an .env
file and the dotenv
library as described here and here. For security reasons, I am not checking the .env
file into my repo, but have instead entered the same variables in the Netlify UI.
Since these Netlify environment variables are only accessible at build time, I store their values in gatsby-config
like this:
// gatsby-config.js
// ...
siteMetadata: {
...
firebaseConfig: {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID
}
},
// ...
So far, so good.
To send these variables to the component that needs them, I query them on the page where they are used:
// pages/app.js
import { graphql } from 'gatsby'
export const query = graphql`
query {
site {
siteMetadata {
firebaseConfig {
apiKey
authDomain
databaseURL
projectId
storageBucket
messagingSenderId
}
}
}
}
`
And then access them in the top-level page component like this:
// pages/app.js
import React, { Component } from 'react'
import firebase from 'firebase/app'
class AppPage extends Component {
componentDidMount = () => {
firebase.initializeApp(this.props.data.site.siteMetadata.firebaseConfig)
}
// ...
}
With this approach, I am able to use the environment variables on the live site. The problem is anyone can use the React Developer Tools to inspect the AppPage
component's data
prop and read my Firebase config details.
So, how can I use environment variables entered in the Netlify UI in Gatsby without making them discoverable in the React Developer Tools? I'm not sure how to get these variables to my components without passing them as props...
Perhaps Firebase has a way to authenticate and get per-user tokens for access?
They do!
Before using Firebase authentication, though, I need to initialize the app itself using my API key.
How to store and access that API key securely is what I'm trying to figure out.
Once the app is initialized, Firebase handles the rest securely.
Probably setup your own authentication server
You only need the firebase PROVIDER_ID which you can safely store in Gatsby env, once a user is logged in they'll get a token back which you can use to call your private firebase services with
https://github.com/firebase/firebaseui-web#using-firebaseui-for-authentication
Thanks for all the replies!
After a bit more digging, I've learned it's actually okay for the Firebase apiKey (and other init settings) to be exposed. Those settings are meant to be included as a simple script tag in the HTML of the production site and Firebase's backend settings will restrict what domains are authorized to use them.
As long as localhost is not among the domains authorized to use the production apiKey, the backend will be secure. So, it's best to create one apiKey for development (with no restrictions) and another for production (which authorizes the intended domain only and not localhost).
I followed the instructions here to create a second key for development and to restrict the production key to the production domain.
If anyone has other insights, feel free to add them!
For anyone else facing this problem.
You can also prefix GATSBY__
on variable name for example in your .env.development
or .env.production
GATSBY_API_KEY=AIzaSyBSzU9n4dbYDl1xxxxxx
then you can access it like this
const config = {
apiKey: process.env.GATSBY_API_KEY,
authDomain: process.env.GATSBY_AUTH_DOMAIN,
databaseURL: process.env.GATSBY_DATABASE_URL,
projectId: process.env.GATSBY_PROJECT_ID,
storageBucket: process.env.GATSBY_STORAGE_BUCKET,
messagingSenderId: process.env.GATSBY_MESSAGING_SENDER_ID,
}
firebase.initializeApp(config)
@ooloth how did you add the field 'firebaseConfig' to the type "Site"? We have to extend that graphql definition somewhere?
@vijaybritto I added it to the siteMetadata
object in gatsby-config.js
:
// gatsby-config.js
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`,
})
module.exports = {
siteMetadata: {
title: `Site Title`,
// ...
firebaseConfig: {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID
},
}
}
Hope that helps!
@ooloth Thanks! It did help. I made similar modifications and it worked.
But if you run this query at http://localhost:8000/___graphql it will throw an error saying that "field firebaseConfig is not defined". I'm guessing that the schema is auto generated but somewhere graphiql UI is not informed of the new schema.
@vijaybritto Hmm...did you try rerunning gatsby develop
after updating your gatsby-config.js
file? Generally any changes to your gatsby-*
files or graphql
-related data requires restarting your development server to see the updates.
If so, this may be a case where you need to delete your .cache
folder and rerun gatsby develop
one more time. This sometimes helps when your graphql
queries seem to be finding an older version of your data and not picking up new fields (like firebaseConfig
).
If none of that helps, feel free to paste your gatsby-config.js
and the GraphiQL
query that isn't working and I'll see if I can spot the issue.
Its for a mini side project. I'll probably get into debugging this while I start my office issue tracker app which we are moving to gatsby. So you'll have to wait for some time to help me 😄. Thanks!
From: Michael Uloth notifications@github.com
Sent: Monday, March 18, 2019 6:00 PM
To: gatsbyjs/gatsby
Cc: Vijay Britto; Mention
Subject: Re: [gatsbyjs/gatsby] [question] How to securely access Netlify environment variables in a Gatsby component? (#7381)
@vijaybrittohttps://github.com/vijaybritto Hmm...did you try rerunning gatsby develop after updating your gatsby-config.js file? Generally any changes to your gatsby-* files or graphql-related data requires restarting your development server to see the updates.
If so, this may be a case where you need to delete your .cache folder and rerun gatsby develop one more time. This sometimes helps when your graphql queries seem to be finding an older version of your data and not picking up new fields (like firebaseConfig).
If none of that helps, feel free to paste your gatsby-config.js and the GraphiQL query that isn't working and I'll see if I can spot the issue.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHubhttps://github.com/gatsbyjs/gatsby/issues/7381#issuecomment-473890149, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ADjZZIDFSmyCE_XmZZlkUZ6Tnrea581Uks5vX4bOgaJpZM4WAIXP.
Most helpful comment
For anyone else facing this problem.
You can also prefix
GATSBY__
on variable name for example in your.env.development
or.env.production
then you can access it like this