How to secure keys when developing Angular Library
Publicly exposing your credentials can result in your account being compromised, which could lead to unexpected consequences, charges and data leaks.
It's important to note that you should not store any password or any other kind of secrets in the Angular library! Ever!
Sometimes it makes development process much easier until we react a point when only certain keys (not secrets) can be exposed. Example: Developing a multipart upload library for AWS S3.
First, create json configuration with "secret" keys:
{
"AWSKEY": "AWSKEY",
"AWSSECRET": "AWSSECRET",
"AWS_BUCKET": "MY_BNUCKET",
"AWS_REGION": "AWS_REGION"
}
Save it under the same folder as karma.conf.js
In karma.conf.js
add section files
:
files: [
{
pattern: 'env.json',
watched: true,
served: true,
included: false,
}
],
Here is larger excerpt from karma.conf.js
:
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
logLevel: 'debug',
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma'),
],
...
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true,
files: [
{
pattern: 'env.json',
watched: true,
served: true,
included: false,
}
],
});
};
Once you run ng test
your file should be available under: http://localhost:port/base/env.json
All we have to do now is to read it in our unit test (example service evaporate.service.spec.ts
):
import { TestBed, waitForAsync } from '@angular/core/testing';
import { EvaporateService } from './evaporate.service';
interface environemntVariables {
AWS_ACCESS_KEY_ID: string;
AWS_SECRET_ACCESS_KEY: string;
AWS_REGION: string;
AWS_BUCKET: string;
}
describe('EvaporateService', () => {
let service: EvaporateService;
beforeEach(() => {
var request = new XMLHttpRequest();
request.open('GET', '/base/env.json', false); // `false` makes the request synchronous
request.send(null);
let envs:environemntVariables = {
AWS_ACCESS_KEY_ID: '',
AWS_SECRET_ACCESS_KEY: '',
AWS_REGION: '',
AWS_BUCKET: ''
}
if (request.status === 200) {
let envVars = request.responseText;
envs = JSON.parse(envVars);
}
TestBed.configureTestingModule({
providers: [{provide: MAILIO_EVAPORATE_CONFIG, useValue: {
awsKey: envs.AWS_ACCESS_KEY_ID,
secretKey: envs.AWS_SECRET_ACCESS_KEY,
bucket: envs.AWS_BUCKET,
awsRegion: envs.AWS_REGION,
partSize: 5 * 1024 * 1024, // 5 Mb is minimun chunk size
}}]
});
service = TestBed.inject(MailioEvaporateService);
});
Let me be clear again. Don't store any secrets in the libraries of any kind. This is solely not to expose AWS ACCESS KEY. The AWS Secret should be server side anyways.
Don't forget to add env.json to your .gitignore
file like so:
**/env.json