[SOLVED] How to provide secrets/tokens to Galaxy app?

I started an app template at GitHub - trusktr/mapapp. The README instructs the user:

make a file ./imports/keys.js here in this project, with your Here auth key:

export const harp = 'AUTH_KEY'

Galaxy does not know it has to do this, so it builds the app without key.js and the app doesn’t work.

How do we get token to Galaxy?

EDIT: the token would be visible in devtools anyway, so security isn’t a concern I suppose. Maybe I should just commit the key. How can a token be passed to a client-side library without it being visible in devtools? Doesn’t seem possible without something more clever like having the Meteor backend negotiate a temporary token with Harp.gl then sending that back to the client for the session.

Hey @trusktr, you can provide tokens using Meteor Settings. You can create a file named settings.json where you can put your configuration options. Then you can initialize your app passing the --settings option to meteor run, meteor deploy, and to the deployment options in Meteor Cloud.

You would run your app like this: meteor --settings path/to/settings.json

If the settings.json contains a key named public, then Meteor.settings.public will be available on the client as well as the server. All other properties of Meteor.settings are only defined on the server. You can see an example here to check how it is used and also read our documentation about Meteor Settings.

Thanks. I suppose this effectively the same as importing a setting from a JS file, in which case the setting is public on the client too.

Looks like I need to ask Here Maps how to get auth tokens dynamically instead of copy/paste.

I marked the title as [SOLVED]. By the way, there’s an official “solved” plugin so that people can mark answers, and topics will shows as “solved”. GitHub - discourse/discourse-solved: Allow accepted answers on topics

In your settings json file, anything under “public” will be included on the client. Everything else is server only. For example

{
  "public": {
      "someVar": "This is available on client + server"
   },
   "private": {
      "anotherVar": "This is only available on the server"
   }
}
1 Like

what is the best way to store secret so that meteor inc cannot access them?

You could use an external service like Doppler (https://www.doppler.com/) or AWS Secrets Manager (credential password management - AWS Secrets Manager - Amazon Web Services). I usually recommend these two, but it is in the plans to implement a way to encrypt the settings.json on Galaxy.

That’s awesome. Is there an ETA on that? Meteor team access to our API keys has been a blocker for our security team to host anything remotely sensitive on galaxy.

Thanks, unfortunately we don’t have an ETA yet. I totally understand your security team, but like I said, you can use an external service like Doppler to store the sensitive information, and still host your app on Galaxy, if you prefer.

I’ve enabled it for the topic owner and staff to be able to mark a response as a solution. You can do so now.

2 Likes

Here is my solution:

  1. Created a file to private/secrets/aws-secret
  2. Stored aws secret value to that file
  3. Added that file to .gitignore
  4. At server startup i read data from aws secret manager using key from the Meteor settings and that secret stored in aws-secret file.

I don’t know any better solutions than this. But so far this is ok! Thank you.

The issue in the original post is that I wanted to provide the client with a token so that it can hit up an API, for example to load map tiles. This means that the token has to be on the client side, so the token leaks from the client (f.e. someone pauses the app in devtools debugger, copies the key, goes and uses it for their own app for free while my credit card gets charged).

Solutions to avoid the key leaking from the client are and someone indefinitely using it outside of the app are:

  • provide a proxy API from the Meteor server after the user is logged in, and the Meteor server proxies to a desired external server so that the token that is used is only in the Meteor server and not accessible on the client
  • or if it is easier to have the token on the client, then the service being used should allow us to request temporary tokens with expiration, so that when a client is logged in we can request (while using a meteor-backend-only key) a token from the external service that expires after some time and give that temporary token to the client. The app will be usable, but a user won’t be able to effectively steal the token unless they are constantly logged into our app and constantly stealing a token.

For either scenario, having an are-you-human check would prevent a user from using our API for free indefinitely. Another problem is some people might try to script the site so it stays logged in (faking user interactions so it seems like a user is doing something, to prevent logic we may put in place to log them out after inactivity).

Without keeping the token on the server, or without expiring it all the time, then all it would take is a single login by a human (even with the are-you-human check) for them to copy out the key for indefinite use outside of the Meteor app.