Angular 2 Environment Variables - Setting basic auth password - javascript

I wrote a very simple service using sails.js. It uses Basic Authentication for access to its services.
I also have a separate front end written in Angular, using the #angular/cli.
I have two sets of environment variables to set for prod and dev. For example:
// dev
ADMIN=admin
ADMIN_PASS=mypassword123
API_ENDPOINT=http://localhost:1337/endpoint
This would obviously be different for prod. My issue is that I am deploying this using Heroku. You can easily set the env vars in heroku, but I don't know how to access them. I know you can set things in src/environments but this would then put my variables in code control.
I have also tried process.env but I learned this is a node.js thing not and angular thing.
How do I access system environment variables from angular2?
example of how I'd us it:
#Injectable()
export class HeroService {
private heroesUrl = 'api/heroes'; // <- this should be grabbed from environment
private adminUser = 'admin'; // this line too...
private adminPass = 'myPassword'; // same with this line...
constructor (private http: Http) {}
getHeroes(): Observable<Hero[]> { ...}
}

Programing Point of View
Use process.env then server side(nodejs) can put them into a structure. Since you are using sails.js, setup a post route or an api call that will send this structure in json format.
Front end(browser) app can make a http.post call to pick it up at run time.
This way the set of parameters are not bundled/hardcoded in your front end app code base.
Security Point of View
If password credential is required for 3rd party service, such call is better handled from the server side like following:
(browser) -- api call --> (your server) -- api call --> (3rd-party)
This way credential to 3rd party is not exposed. And api call to your server should be protected by some authentication mechanism.

Related

How to manage data for the tests?

I have only one account - admin by default. I need to change user permissions to non-admin one. I believe that I have few options available (not great yet can be used)
Create a new endpoint on a server just for testing - to make it possible for non-admin user to update those permissions. This idea seems pretty odd to me to change something like that.
Have multiple users to be able to switch between them for different roles (all in all not that simple for now).
Connect to db within tests and make those changes on db - probably easiest option
Is it OK to create new endpoints for testing e.g. /publish-cypress? Is it OK to populate the database just for tests by running some operations on db?
On my personal opinion you shouldn't create testing endpoint.
What you should be testing is the method that will be called by these routes (Your service), and for front-end you can 'fake' these call to the api.
The simplest way to do that is to use something similar ton interfaces (you might want to look at typescript ;) )
An example to fake these calls in your tests:
I'll go with typescript as it'll be mush easier to understand (less code)
//here you define all calls possible to your api
//dont forget to always pass the gateway by reference so that you can change whenever you want between fake & real
interface MyGateway {
changeUserPermission(userId, permissions);
}
//here do the actual implementation that will be used by your app
class MyApiGateway implements MyGateway {
public changeUserPermission(userId, permissions) {
//here is your real api call with fetch, axios or whatever
fetch('http://example.com/perms')...
}
}
//now you can do another implementation for testing purposes
class MyTestGateway implements MyGateway {
//here you can return hard values or do whatever you want so that your app doesn't depends on you backend
public changeUserPermission(userId, permissions) {
console.log(`Updating ${userId} is ${permissions}`);
}
}

How to secure API Keys in Environment Variables in a Vue CLI 4 and Electron project

I'm trying to develop a desktop app which would need to make a few private API calls, authenticated using some secret keys.
The keys are created for me by external IT service providers outside of my organisation - they are responsible for the security so there are a few constraints:
They said even though they have already taken steps on their end to secure the API and there are mitigation strategies in place even if a breach happens, but still they would like to make sure that I treat the keys with a security-conscious mindset and take whatever steps possible on my end as well to make sure they remain secured.
I'm not allowed to just create random middleware / gateway on a private server or serverless platform to perform the API calls on my app's behalf as these calls may contain business data.
I have done some research and from what I can find, the general recommendation is to set up a ".env" file in the project folder and use environment variables in that file to store the API keys.
But upon reading the Vue CLI documentation I found the following:
WARNING
Do not store any secrets (such as private API keys) in your app!
Environment variables are embedded into the build, meaning anyone can
view them by inspecting your app's files.
So, given the constraints, is there a way to store these keys securely in a Vue CLI 4 + Electron Desktop app project?
Thanks.
In general, especially if you have a lot of environment variables, it would be better practice to store environment variables in a dot env file (.env), however, it's possible that this file could be leaked when you package your electron app. So, in this case it would be better to store your environment variables from the terminal/command line. To do so follow this guide (https://www.electronjs.org/docs/api/environment-variables).
Keep in mind anything that requires the API key/private information try to keep it on the backend, i.e., the electron process and send the results to the Vue front end.
Here's an example of how you could implement this:
On windows from CMD:
set SOME_SECRET="a cool secret"
On POSIX:
$ export SOME_SECRET="a cool secret"
Main process:
// Other electron logic
const { ipcMain } = require("electron");
// Listen for an event sent from the client to do something with the secret
ipcMain.on("doSomethingOnTheBackend", (event, data) => {
API.post("https://example.com/some/api/endpoint", {token: process.env.SOME_SECRET, data});
});
Client side:
const { ipcRenderer } = require("electron");
ipcRenderer.send("doSomethingOnTheBackend", {username: "test", password: "some password"});
Also note, to use the ipcRenderer on the client side nodeIntegration needs to be enabled.
Here are some more resources to help you get started:
https://www.electronjs.org/docs/api/ipc-renderer
https://www.electronjs.org/docs/api/ipc-main

Node.js best way to store variable to be used between multiple modules

I have following Node.js app structure:
- main.js - main file
- ./requests/requestSetName.js - different functions sending different requests to API, so I have e.g. userRequests.js, vechicleRequests.js etc.
First thing I do in main.js is I send a request with login credentials to get access token. For all other requests I need to put this token in the request header. So each function in all modules in request folder needs to have access to it.
What is the best way to store this token and to be able to use it across different modules in Node.js ?
I think you shoud use classes for each request file and inject another class (Globals) witch contains the token , in the constructor of each request class, typescript should make It clean.

Meteor: How can I get useraccounts package to write a new user doc into a remote collection?

I'm using the packages accounts-password and useraccounts:bootstrap and it all works fine, meaning the sign-on form creates a new doc in the Meteor.users collection. But I don't want any collection on the client facing app, hence I do have a second app running to which I successfully connect via DDP.connect() and I can exchange all necessary docs/collections via pub/sub and calling methods on the remote app.
The only thing that doesn't work is the useraccount doc. I've used (on the client app):
remote.subscribe('users', Meteor.userId(), function() {
});
and (on the remote app):
Meteor.publish('users', function() {
return Meteor.users.find({});
});
even though I'm not sure if there is a pub/sub already included in the package. Still, the doc is written to the local (client) app and not to the remote app.
How can I achieve this?
useraccounts:core simply makes use of Accounts.createUser on the server side (see this line) within a method called from the client-side (see this another line).
So the new user object is created from the server side and not from the client (though it flows all the way down to the client thanks to the DDP and default users subscriptions...).
If you're really looking to change the defaul behaviour provided by the Meteor core Accounts packages (accounts-base, accounts-password in this case...) you should try to override the Accounts.createUser method which is were all begins...
In any case be warned that the current user is published to the client by default: see these lines
Finally, to prevent useraccounts:core to use the Accounts API you could try to override the AtCreateUserServer method and deal with the creation of a new user on a remote application inside there.
Package accounts-base provide such functionality.
The accounts-base package exports two constructors, called AccountsClient and AccountsServer, which are used to create the Accounts object that is available on the client and the server, respectively.
Nevertheless, these two constructors can be instantiated more than once, to create multiple independent connections between different accounts servers and their clients, in more complicated authentication situations.
Documentation: Accounts (multi-server)

Code organization (node, js involving models, service, route and mocha tests)

I'm quite a beginner in the project architecturing / structuring side of things.
The overall project currently looks like:
route/home.js
service/appService.js
models/appModel.js
In the route file, I require appService.js.
appService.js takes care of some API calls to external services, such as getting an access_token from such API service.
When I receive the access token, a callback is made in appService which calls appModel (appService requires appModel.js), and in turn appModel stores the access token in the database. Then, another callback is called in appService which in turn does runs the callback that the route page provided, then I make a redirection.
I am using mocha for testing the service and model files.
My service file is requiring the model file, so when I create a mocha test for the service file, the model is called indirectly as well.
Should I require the model in my route file instead of the service file, and run the model function in the route, once I receive the access token response from the API in the service file? What do you suggest?
Normally you would have some kind of bootstrapper or service container which handles loading your files.
That way you avoid tight couplings between the different parts of your application and can exchange them out when testing (such as swapping the DB for fixtures).

Categories

Resources