Best Practices for Storing Tokens

Greetings. We are working on a Gatsby site that we’re hoping to deploy to Netlify. One of the APIs we are accessing (Getty Images) we have a private API key / secret that we’re storing in Netlify server side variables and using it to access the API. Upon the first API request the API will return a token that should use to access any further API calls for 30 min after which we would be issued a new token.

My question is what is the Netlify best practice for storing this token server side and proxying the API requests so the token is used but not visible client side?

We’re looking into Dynamo DB on AWS as the most likely solution. But I wanted to see if there is a better way to do this as it seems like an over kill.

Hi, @JpMaxMan, that answer depends on if you are calling that API during the site build process or at browse time.

If it is during the site build process, I would recommend storing the API key in an environment variable:

If on the other hand the API is used after the site is deployed, then the recommended best practices are to use a serverless function as a wrapper. This keeps the key out of the end user’s browser. More information can be found at the support guide link below:

​Please let us know if there are any questions and, if so, which situations above applies to your site.

Thanks for the response :smile: So to answer your question the API is used after the site is deployed. It is used to query the Getty image library - so hundreds of millions of pictures there.

I did see the token hider project. The problem with that approach is the token is assigned dynamically. So the API works by using an API key / secret which we can store as build variables and use your approach to make the initial API call. But then the API returns a dynamic token to be used for subsequent API calls and is valid for 30 minutes until it assigns a new token. So you need a way to store that token server side with some sort of flushable data store so the token can persist just for the session then be discarded.

Cloudflare workers have a key value store that accomplishes this nicely. My hope was that Netlify had something similar where it had a temporary dynamic data store to remember and use the token for a short period of time.

I looked at Netlify Snippets and Netlify Metadata but neither seemed to meet the use case.

Hey @JpMaxMan,
I wonder if you could build a custom Build Plugin for this?

So onPreBuild, make the initial call with your existing API keys, and then set a TEMP_TOKEN environment variable with what you get back?

As that README for Build Plugins explains:

The index.js file runs in a regular Node.js environment and can use any Node.js core methods and modules. Environment variables can be accessed and modified with process.env .

So seems worth a shot? Would love to hear if this ends up working for you.

1 Like

I’m not sure if this would work, but have you tried netlify’s lambda functions for this? They’re functions that sit on netlify’s server, away from your private public code, and you can put some sort of password in your query params? (I’m a newbie at using netlify, so it’s just an idea)

You can access process.env variables from there, but I’m not sure if you can set them from there. Also, maybe you can simply store the token in a regular variable that lives in your lambda function file.

For example:

from your app, make an axios request to ‘./netlify/functions/token’

in your functions folder:
functions/token.js

let storedToken = process.env.token || 'hard-coded-token'

exports.handler = function(event, context, callback) {
   let { token } = event.queryStringParameters

   try{

      callback(null, {
          statusCode: 200,
          body: storedToken, // this body has to be a string
       })

   }catch(error){
        callback(err)
   } 
}

Thanks @maiya and @jen for the responses.

Yes, so we are using a Netlify function (lambda) with a dynamo DB on AWS as our current solution.

The issue is really less with the ‘functions’ and more with the storage. So, the take away - I think - is Netlify has no built in method for key / value storage and recall the way that the cloud flare workers do.

In an ideal world we would be able to do this within the Netlify environment without having to drop down to a self serviced AWS solution for storage. And given that Netlify is so keen on JAMstack I had just assumed surely there would be a built in way to store and proxy temporary tokens provided by an API.

1 Like

Thanks for the response @maiya and at @jen

So Netlify Functions (Lambda) with AWS Dynamo DB is the solution we ended up with.

The issue is really much more with storage vs. functions. I had assumed there would be a built in Netlify method for temporarily storing, recalling, and proxying tokens handed out an API to persist the initial auth(z).

Given the JAMstack methodology I am surprised this doesn’t exist, so thought I’d inquire as to best practices.

The Netlify function / Dynamo approach works but it just feels kludgy.

1 Like

@jen When you quote the Build Plugins readme:

Environment variables can be accessed and modified with process.env .

I’d like to ask not about build plugins, but in the serverless context:

From a Netlify Function I can access and read process.env .

Can I set the value for an env variable, from a Netlify Function?

By “set” I mean have the value propagate back to the settings/deploys#environment UI in Netlify, so that the new value can be read by later instances of a lambda.

My understanding is this goes against what process.env is supposed to do, but your emphasis on “accessed and modified” in this context puzzled me…

Thanks!

Hey @mrazzari,
No, I don’t currently know of an easy, secure way to set an env variable from a Netlify Function. The Build Plugins work pretty differently: they’re part of the build process of your site, so have read/write access to your build environment. This is as opposed to a function, which is an AWS lambda “under the hood” and is only usable once it’s been deployed on AWS. The functions come in at a different part of the process and have a different level of access than plugins.

Let me know if that helps or if we can answer any other questions on this!

1 Like