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