Storing API keys in MEAN Stack - angularjs

Looking for the best way of storing(securely) a Google Places API key in a MEAN stack. I was going to use a .env file but I am not sure how to go about implementing this. My current solution is having express pull in the .env variable but then I am not sure what route to take from there to insert the key into the script tag. I can't find anything from angular on how to use a template for this, so I came to the conclusion I would have to use another template library like handlebars. I really do not like this approach, is there another 'best practices' way for solving this problem?

I recommend using module node-env-file. That's what I use for my projects and I'm pretty happy with it. It's very simple to setup (check out their docs) and works like a charm. It reads your variables from an .env file and embeds them into your Node project.
.env
# your environment variables
API_KEY1=abcd123
app.js
var env = require('node-env-file');
var API_KEY1 = process.env.API_KEY1;

I do the following in one of my projects - it works for me with my nodemon development environment. I store the same data via config vars in Heroku so as not to have to include the keys in my repository.
// loads confidential parameters to inject into process.env
var googlekey = fs.readFileSync("./ignored/privatekey.pem", "utf8");
var config = require("./server/config/local.env");
config.PRIVATE_KEY = googlekey;
//run server using nodemon
gulp.task('serve', function(){
return nodemon({
script: 'index.js',
watch: 'server/',
// ignore: ['app/**/*', 'dist/*', 'node_modules/*'],
env: config
})
.on('start', function () {
// done();
});
});

I'm going to assume you're using what Google refers to as a 'Browser key'. If, however, you're using a 'Server key', then you shouldn't be passing the key to your client-side code anyway.
If you're using Express response.render() to generate the HTML, you can pass the API key into res.render as a local, and reference it within your HTML or template.
The following is a snippet from a jade template I'm rendering with Express, that does something similar with the Stripe API:
extends layout
block head-content
script(src='https://js.stripe.com/v2/')
script.
// <![CDATA[
Stripe.setPublishableKey('#{stripePublicKey}');
// ]]>
It sounds like you're storing the key in an environment variable, so you could pass it into the Express rendering engine thus:
res.render('index', {stripePublicKey: process.env.STRIPE_PUBLIC_KEY});
It also sounds like you want to avoid using jade or some other template engine, so you can use EJS, which will allow you to use 'pure' HTML, but with variables. Here's a good tutorial for getting started:
http://robdodson.me/how-to-use-ejs-in-express/
If you have a large amount of content already, and you don't want to have to rename all of your existing .html files to .ejs just to get that one variable passed in, you can do this:
app.engine('html', require('ejs').renderFile);
as described in more detail here:
http://expressjs.com/api.html#app.engine
It sounds like you're already working on the other best practices list under 'Best practices for securely using API keys' at the link below, but be sure especially you're following the guidance regarding restricting access by referrer URL.
https://developers.google.com/console/help/new/
Best of luck!
Tim

Related

global variables not work in React Native - Expo

Hi guys i try for create global variables with file .env but not works i use react native expo
i wrote process.env.API_URL but not found this variable. What i to do for works ?
I'm desesperated
I read https://www.npmjs.com/package/react-native-dotenv and https://docs.expo.io/guides/environment-variables/ but not works for me.
I need HELP !!!
https://docs.expo.io/guides/environment-variables/#the-app-manifest-env
If you have installed the expo-constants module in your managed
workflow project, you can access the app manifest's properties. One of
these properties is the .env property, a property that is only
available when running expo start. As the name suggests, it contains
some of your system-defined environment variables. For security
reasons, only the variables that starts with REACT_NATIVE_ or EXPO_
are available.
If you want the API url to be available it needs to be prefixed with REACT_NATIVE_ or EXPO_
Defined
REACT_NATIVE_API_URL=....
or
EXPO_API_URL=....
Accessed via
process.env.REACT_NATIVE_API_URL
or
process.env.EXPO_API_URL
Edit
If using the react-native-dotenv module
Usage
Add your env key-value pairs to your .env file
API_URL=....
Now import it in your .js file
import { API_URL } from 'react-native-dotenv';
I ran into so many issues getting environment variables to work. Oddly, the most highly recommended package was react-native-dotenv, and the first line of code in index.js is to require('fs'), which is a Node module that isn't available in React Native.
Anyways, I ended up creating a new context to handle Environment Variables. I don't have logic to automatically import variables based on environment, but that's as simple as commenting out one line.
Create a JSON file with your variables, import it into your context, and place it at the top of your app.js return, allowing everything in your app to consume it. From there, import it with useContext() as you would any other context, and you have access to all your variables.
Edit: After repeated issues, I decided to simply only use production variables for app testing. It's not ideal at all, but I'm sure many are in the same position as I'm in where the only real difference in variables is the route name for the API (local test server vs. production server). Unfortunately, both iOS and Android do not support http requests, or https requests with self-signed certificates without editing config files. Those config files are not available if you're using an Expo managed flow. Thus, my only choice was to simply do my testing on the production API. Luckily, I have good logs to go by, and the API itself is fairly mature and has endured plenty of testing via the web React app.
If anyone has a better solution, I'd love to hear it.

How do I make AngularJS work in Google Apps Script?

I am currently following this tutorial:
https://scotch.io/tutorials/build-a-real-time-scheduling-app-using-angularjs-and-firebase#connecting-to-and-using-firebase, but it is not working as I have it in Google Apps Script.
I am trying to use AngularJS in Apps Scripts. However, the documented fixes to make AngularJS work is documented to use the following line of code:
var ui = HtmlService.createHtmlOutputFromFile('myPage')
.setTitle('My Title');
ui.setSandboxMode(HtmlService.SandboxMode.IFRAME);
Source: Angular JS in Google Apps Script
But I am not sure where to put this in my Code.gs file? I have a function.doGet, so does it go in there?
Right now, my Code.gs is as follows:
function doGet() {
return HtmlService.createHtmlOutputFromFile('index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
Thanks for your help!
HtmlService.createOutputFromFile(...) returns an instance of the HtmlOutput class, which has the setSandboxMode(..) method. Assuming that you have a file "index.html" in your Apps Script project, your code is correct:
function doGet() {
return HtmlService.createHtmlOutputFromFile('index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
doGet is the method called by the Apps Script runtime when user navigates to your app's URL, and it should return the fully formed HTML that you want to render (which can include references to externally hosted js, css, etc.)

Different base url for page routing and templates/partials/RESTful API

My Angular app is splitted into several subapps. I'm working with laravel which is also responsible for the routing between the subapps.
So there are the following urls handled by laravel:
ModuleX: /moduleX
ModuleY: /moduleY
ModuleZ, Item n: /moduleZ/item-n (unlimited amount of items)
And finally on top of these there are my 3 Angular subapps.
So for example: /moduleZ/item-1/#/hello/world
Additionally the templates, partials and a RESTful API are served by laravel under the following urls:
/templates
/partials
/api
If I set the base url with the html tag <base href="http://www.example.com/app/"> I can use relative urls for templates, partials and the api but not for the routing. I'll allways have to add the module url part like that moduleX/#/hello/world.
If I set the base url like for example <base href="http://www.example.com/app/moduleX/"> I can write all links like #/hello/world but the templates, partials and api requests aren't working anymore.
The whole app also sits in a subfolder so I can't just use for example /templates.
So basically my problem or the question now is, what's the best way for handling the different base urls? I don't really like it to prepend the module name to every link.
Look it's might be a particular solution, but may be you should use filters for urls?
For example:
.filter('routeFilter', [function () {
return function (route) {
if (some condition mean this direct html link){
return 'MODULE-X/' + route;
}else{
return route
}
};
}])
I would suggest you let (sub-)apps know their real base not the parent's one, but you make the server responsible for climbing the path hierarchy to find higher level shared resources for missing local ones. This also makes it very easy to prototype new sub-apps, test changes to common pieces independently first, etc.
In a webserver like Apache, this would look like a rewrite rule (conditional on not finding a file) it just substitutes the same file in the parent hierarchy.
In laravel (according to the router docs) it looks like you can add optional 'directories' to your current rules, i.e.:
Route::get('/.../app/templates/{name}', function($name)
...
becomes:
Route::get('/.../app/{module?}/{item?}/templates/{name}', function($name, $module, $item)
...
You could then use $module and $item if you need to test a resource change with specific sub-app/items.
The drawback in making the server responsible for handling inheritance is the independent client fetch/cache of identical resources with different paths. But you can at least choose between large file inefficiency or access latency by using either rewrites or redirects. You can also always hardcode significant paths in production clients later and still benefit from having a hierarchy for testing and graceful handling of occasional errors in client side links.
You can do it in a simpler way if you use combination of service and directive.
You can implement a directive similar to ngHref which when given a link will transform it and append the given link back. It will be injected with a service which will give it the base url or relative url or anything module specific.
This service which is injected in directive will be configured using serviceProvider in app.config block of each sub-app. Since angular injector have only one instance of each service I think you will need more than one injector or one injector per sub-app. Its unclear whether they share injector among them in your app.
You can configure each service according to module to return different base paths. Which will be appended by directive to each link every time.
With this you can use <base href="http://www.example.com/app/"> and that should solve your problem.
I haven't written any code but I can help if you need it.

Can one host an angular.js based static blog on Github?

I know one can host a Jekyl based static site/blog via Github pages. Can one do the same with a static site/blog based on AngularJS?
You can but you can't use html5 mode (removes the # from urls). If you use html5 mode, you have to redirect all requests to the root url since its a single page app. Since you can't use server side code on GitHub pages, you can't do this. So, if you don't mind the # in the url, go for it. If you want to use html5 mode, you need to look for hosting elsewhere.
From the Angular docs...
"Using [html5] mode requires URL rewriting on server side, basically you have to
rewrite all your links to entry point of your application (e.g. index.html)"
EDIT:
You can make use of some clever hacks to make this work if you really want to. The hacks are outlined in detail here. In summary, you rename your index.html to 404.html and github will serve it at all routes
I would say yes considering all the angular UI github pages are in fact angular apps with demos:
http://angular-ui.github.io/
http://angular-ui.github.io/bootstrap/
etc
There is one conflict between Jekyll and Angular to be aware of.
Liquid, which is included in Jekyll also uses {{ }} for evaluating expressions. To change the expressions that angular interprets (so it doesn't conflict with Liquid) use:
var myapp;
myApp = angular.module('myApp', []);
myApp.config([
'$interpolateProvider', function($interpolateProvider) {
return $interpolateProvider.startSymbol('{(').endSymbol(')}');
}
]);
Check out this blog post
Yes, you can. I recently played around with AngularJS/Typescript and github pages and was able to deploy the site.
Since AngularJS is just javascript, you can actually use any decent webserver, e.g. github pages.
Here is the demo.
You can find source code here. This repository contains typescript source code which you have to compile in order to get the appropriate javascript file. Then you basically put this include this file into your index.html and you are done.

How to provide configuration to AngularJS module?

Currently I am combining a traditional application with some dynamic parts written using AngularJS. I would like to provide some configuration from my server to my module. In this case I would like to configure the application 'base' URL. All templates can be found at a specific location and this location is determined by the server.
So I tried something like this:
angularForm.config(
function($routeProvider, TemplateLocator) {
$routeProvider.when('/', {
controller : TestController,
templateUrl : TemplateLocator.getTemplate('FormOuterContainer')
});
});
At the server:
<script type="text/javascript">
angular.module('BoekingsModule.config', []).provider('TemplateLocator', function() {
this.$get = function() {
return // something
}
this.getTemplate = function(name) { return 'location...'; }
});
</script>
However, I am not sure this is the right way.
So in short: how can I provide some (external) configuration to a module without having to change the module itself?
There are several things you can do
Render the locations in the js on the server.
Pro: less requests -> better performance (usually)
Cons:
combining server side rendering with an SPA makes the system more complex, leading to higher maintenance costs.
it is harder to properly compress your js files if you want to mix in server side rendering, embedding js in html is also ugly.
Extract the template location to a service.
From this service you could use a $resource to fetch the data from the server in json format. This keeps things simpler, but it could also increase your web server's load.
Wow it has been a long time since. I completely forgot about this post.
So, in the end I decided it was better to use another approach. Like iwein said, combining SPA with server side rendering makes the application a lot more complex. Therefore I extracted the SPA part into a separate application which in turn is referenced from (in my case) the JSP.
When my module needs some additional configuration, it gets it using a REST API. This way the SPA part of the application is completely decoupled from the server-side rendered part.

Resources