Using auth tokens in .npmrc - npm

I have a project where we use font awesome 5 library. I followed the instructions that are written here and added an .npmrc file with my auth token.
Is this a safe behaviour to put this in a repo? I want the devs to have access to it, but if the repo goes public we might be exposing the token.
What is the best practice in situation like this?

UPDATE 2021-05-02
This answer remains questionable - see the comments below. I no longer have access to a private ($paid) npm account anymore, so I can no longer test to answer questions.
Perhaps try #konyak's answer.
It is definitely NOT a safe behavior to put the token in any git checked file, including .npmrc.
Below are the steps your team can take to safely leverage your npm token.
There are two different environments to consider:
each developer's local dev machine
the app's deployment platform
local dev
Following the Global Set Up instructions you linked to in your question, is not the solution.
Create the .npmrc file similar to the "Per project" instructions, but substitute your real token with a variable name, prefixed by $. ie:
#fontawesome:registry=https://npm.fontawesome.com/
//npm.fontawesome.com/:_authToken=$TOKEN
npm will detect an environment variables file named .env. So, in a .gitignored .env file, add your secret key value pair, ie:
TOKEN=ABC123
You can also prefix the variable name with "NPM_CONFIG_", according to the npm-config docs, ie:
NPM_CONFIG_TOKEN=ABC123
Now, when the dev runs npm i, font-awesome dependencies will load from the private repo.
NOTE: Don't follow the current npm-config docs about the environment variables syntax! See this stack overflow answer, ie:
đź‘Ž BAD npm-config ENVIRONMENT VAR SYNTAX đź‘Ž
${TOKEN}
đź‘Ť GOOD npm-config ENVIRONMENT VAR SYNTAX đź‘Ť
$TOKEN
app deployment platform
Do all the steps from the local dev section above, PLUS:
create an environment variable on the platform with the same name as in the .npmrc file.
If your app host is Netlify, see their Build Environment Variables docs.

https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow
Export your secret token into your session, e.g., export NPM_TOKEN="00000000-0000-0000-0000-000000000000"
Inside your ~/.npmrc, add //registry.npmjs.org/:_authToken=${NPM_TOKEN}

I put the relevant config line, with the token in plaintext, in a .npmrc file in my home directory. You can then use filesystem / OS permissions to protect it, avoid accidentally checking it in to source control, and NPM will read it automatically with no further action on your part.
In the project directory, we have .npmrc with a scoped registry declaration only (#fontawesome:registry=https://npm.fontawesome.com/), and a separate ci.npmrc which has that plus the variable-substitution authToken assignment:
#fontawesome:registry=https://npm.fontawesome.com/
//npm.fontawesome.com/:_authToken=$FONTAWESOME_NPM_TOKEN
The CI build job just has to replace .npmrc with ci.npmrc before doing anything with npm, and set a secret environment variable with an auth token assigned to the appropriate service account.

Related

setup npmrc _auth for 2 registries

I have a set of js libraries, lets call them myLib, it is in form of workspaces so I have myLib-common, myLib-hello, myLib-world and so on. In the root of the myLib, I have .npmrc file to set npm registry and authentication.
I have 2 npm registries in nexus:
https://nexus/repository/project-javascript
https://nexus/repository/project-javascript-dev-repo
the first one is proxy registry that uses some other internal packages and then npmjs registry in order to be able to install dependencies. The second one is to publish new versions of the myLib packages for others to use.
Both of those registries requires authentication (for now, it can be the same user). When I add _auth into my .npmrc file, it works fine both for installing depndencies and also for publishing new versions into second repository. But I get warnings from npm that this is not ok. I've tried to "scope" the _auth token but it works just for the first registry and it wont let me publish packages due to authentication.
I have tried various versions like
registry=https://nexus/repository/project-javascript
//nexus/repository/project-javascript/:_auth=<base64>
//nexus/repository/project-javascript-dev-repo/:_auth=<base64>
and also
registry=https://nexus/repository/project-javascript
//nexus/repository/project-javascript/:username=user
//nexus/repository/project-javascript/:_password=<base64>
//nexus/repository/project-javascript-dev-repo/:username=user
//nexus/repository/project-javascript-dev-repo/:_password=<base64>
even extra quotes around tokens and so on but I'm still hitting not authenticated when publishing. When I remove everything and have just
registry=https://nexus/repository/project-javascript
_auth=<base64>
it works just fine for both installation and publish.
One more thing. I kinda need to have the auths in git and I'm still kinda unaware of how _authToken works (I believe it is setup locally, so everybody who works with the project would need to run their own npm login resulting in different authToken).
I've ran out of possible options here (the ones I was able to find through google). Is there a way I can set it up properly? Or way to easily debug the process of publishing so I can see where/how the token is loaded?

Should .npmrc be ignored?

The Fontawesome Pro instructions describe placing a secret key in a .npmrc file but it is unclear how this file should be managed. Specifically, should this file be ignored by Git?
The Fontawesome Pro instructions are correct as an example of the general approach to managing sensitive information in a .nmprc file :
all sensitive values there should be replaced by environment variables, and
those variables should then be defined as managed secrets in whatever environment the repo will be pushed to.
My answer would say it's best to ignore it and not push to repo. as if you have multiple Engineers contributing changes to a generated package for push to the registry each developer will have to have their own .npmrc file and it' unlikely that you'd ever want that pushed to the repo as each attempt would overwrite/conflict.
I could imagine a scenario where you'd like to automate by using a single credential for all devs and thus one global .npmrc file but that is an obvious security faux pas in my view.

Switching from NPM to GitHub Packages

I have a NPM package with a small user base, yesterday I created a new version and wanted to release it. I thought that I might as well make use of the new GitHub Packages and so I setup everything as GitHub suggested and released!
Now the problem is that I still have the old NPM page running on version 2.0.2 while everyone currently uses this as their dependency while the new GitHub package is on 2.0.4, Is there a way to 'synchronize' these two. Of course the GitHub Packages uses the <USER>/<PACKAGE> labeling while NPM just uses <NAME>.
Is the only thing I can do to publish on GitHub Packages and on NPM and just try to move users away from the NPM page?
If your publishing a public package, your better off just publishing it on NPM, as that is what most developers are used to.
I use GitHub Packages at work and the only advantage is that is effective free for hosting internal packages, as we are already paying for GitHub anyway. If it wasn’t for the zero price we wouldn’t be using it.
If you really want to force all your users to migrate to GitHub packages, and have to set up npm to work with it you could mark you old version npm deprecated and use that to point people to the new version.
https://docs.npmjs.com/cli/v6/commands/npm-deprecate
Here is another solution, but there is a catch.
Change your registry.npmjs.org package content to
index.js
export * from '#schotsl/my-package';
Now your registry.npmjs.org package is (almost) pointing to your npm.pkg.github.com package.
Only almost because any development directory for a project downstream of registry.npmjs.org/my-package, must configure the scope-to-server mapping for #schotsl/my-package to npm.pkg.github.com in a package manager config file.
In the case of package managers 'npm' and 'yarn' (v1) that can be done in
an .npmrc file at the same level as package.json.
The required .npmrc content is
#schotsl:registry=https://npm.pkg.github.com
# Github PAT token, packages:read authorization only ok
//npm.pkg.github.co/:_authToken="ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
The first line is the scope to server mapping.
The second line is a Github personal authorization token (PAT) with at least package:read permission. It is actually pretty liberal. A PAT with package:read issued from any github account will allow read access to every github accounts packages.
For the 'yarn' v2 package, the .npmrc file does not work, and instead a couple of keys need to be set in .yarnrc.yml.
Unfortunately there is no way to set the scope-to-server mapping and the token inside the registry.npmjs.org/my-package package itself.
Putting the .npmrc file in there doesn't work, it is ignored. And that wouldn't be a good solution anyway, because not all package managers read .npmrc files.
That is the 'catch' - using npm.pkg.github.com packages requires package manager specific config settings to be made by every downstream developer.
In addition, what if two different upstream packages have colliding scope names, each mapping to a different server? The current config methodology fails in that case.
Feature Proposal not current behavior
Ideally, there would be a common interface agreed upon by all package managers inside package.json - and the scope-to-server mapping would be defined in the package that directly references the scope. For example, in the package.json of my-package on registry.npmjs.org
{
dependencies:{
"#schotsl/my-package":"1.0.0"
},
registries:{
"#schotsl/my-package":"https://npm.pkg.github.com",
},
auths:{
"https://npm.pkg.github.com":"ghp_XXXXXXXXXXXXXXXX",
},
}
Then downstream users would not need to config for each scope, and predictable (and risky) problems with scope name or package name collisions would not occur.
But that is not the way it is. Therefore Github Packages (npm.pkg.github.com) doesn't really seem to be a feasible way to provide public packages which may become dependencies of other public packages. No problem for private packages though.

Vue-cli 3 Environment Variables all undefined

I've tried all of the solutions out there but none seem to work for me. I just want to store some values in a .env file within my Vue app but simply trying to log process.env returns an empty object from within the component.
My .env file
VUE_APP_URL={api url}
VUE_APP_TOKEN={token}
My plan was to set these environment variables to data properties but it always returns undefined. If I do console.log(process.env.NODE_ENV) from webpack.config.js it will show that I'm in development but if I tried doing the same from within the component like
mounted() {
this.$nextTick(() => {
console.log(process.env.VUE_APP_URL);
})
}
It just returns undefined.
A few tips for people who land here:
Make sure your .env files are in the project root folder (and not in say src/)
Variable names should start with VUE_APP_ if to be statically embedded into the client bundle
Restart the dev server or build your project for changes to take effect
If you are migrating from a webpack based solution make sure that you replace : (from JSON config) with = (dotenv format). Easy to miss
Make sure you've saved any changes to your .env files.
In old Vue versions environment variables were defined in e.g. config/dev.env.js instead of the .env files in root
I figured it out - I had to install dotenv-webpack and initialize it in webpack.config.js which is odd because none of the docs stated that I needed to do so.
Install dotenv-webpack and configure the vue.config.js file as follows.
npm install dotenv-webpack --save-dev
Add this to your config file:
const Dotenv = require('dotenv-webpack');
module.exports = {
configureWebpack: {
plugins: [
new Dotenv()
]
}
}
In your .env file make sure you add VUE_APP_ before your variables like this:
VUE_APP_VAR1=example
VUE_APP_VAR2=value
Now you can access these variables in your Vue application:
console.log(process.env.VUE_APP_VAR1); // "example"
console.log(process.env.VUE_APP_VAR2); // "value"
Here some links for reference:
https://www.npmjs.com/package/dotenv-webpack
https://cli.vuejs.org/guide/webpack.html
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables
so I use
VUE_APP_API_URL (this doesn't work)
then I change it to
VUE_APP_APIURL (this works)
hope it helps
If your vue-cli version is higher than 3.x and you put your .env files in root directory like said in comments. Than you can access your environmental variables from components (like this process.env.VUE_APP_YOUR_VARIABLE).
As said in vue-cli docs
Only variables that start with VUE_APP_ will be statically embedded into the client bundle with webpack.DefinePlugin. You can access
them in your application code: console.log(process.env.VUE_APP_SECRET)
I put my .env file in the root directory and appended each variable with VUE_APP_.
To demonstrate this, for example, if the variable you want to use is API_BASE_URL
In your .env file, you put the variable as VUE_APP_API_BASE_URL=baseurl/api/v1
To access it in your files, you do process.env.VUE_APP_API_BASE_URL.
CAVEAT:
Never put any sensitive information you don't want anybody to see, on your front-end. The most common thing you won't want anybody to see (as regards web development) is your API Key. There are real consequences to doing this. This is one such example of someone who has been burned exposing API keys to the public.
However, even if you put your sensitive data in a .env file and add the .env file to a .gitignore file (hence not pushing it to a Git repository hosting service e.g Github, BitBucket, Gitlab etc.), your data is still not safe on the front-end. It's only safe when this is done on back-end code as it will be hosted on a server.
In the front-end, anyone who is determined enough can find your sensitive information. All your information is available on a browser and all that person needs to do is to open the dev tools and check the Sources tab, and BOOM all your sensitive information is laid bare.
Environment variables on the front-end are only useful when you want one reference point for NON-SENSITIVE information, such as a BASE URL, as seen in the example above. A BASE URL can change during the course of development and you won't want to change all references in the application folder manually. It is tedious plus you may miss a few, which would lead to errors.
If you want to avoid exposing your API keys and other sensitive information you may require on the front-end, take a look at this article.
This is what worked for me. I previously created my .env.development and .env.production files in the root folder by manually by right-clicking in the Exploer in VS Code and adding a new file. This kept giving me undefined.
I deleted the files and first installed npm install touch-cli -g
Once installed, i added the environment files as such touch .env.production and touch .env.productionand itworks. So I think there's a difference between how these env files are generated.
NOTE: I do not have webpack installed. Just using the vue cli to build
VS Code ExplorerChrome Developer Tools
IF you are using VITE, use VITE_ in stead of VUE_APP
Vue CLI dotenv usage suffers the inability to provide the .env variables other than prefixed with VUE_APP_. This is OK but this is far not enough to satisfy any even little serious web project that wants to conveniently and securely manage its (sometimes huge) list of variables for different environments.
Here is the solution that makes use of .env variables as convenient as on backends with dotenv.
With this solution you could access your MY_EXTERNAL_API_KEY from your .env[.environment] file in your code like this const key = process.env.MY_EXTERNAL_API_KEY.
It provides:
The convenience of using non-prefixed with VUE_APP_ variables' names and use .env variable expansion feature (use ${VARNAME} kind of variables)
The necessary security: your variables are neither available at browser console with console.log(pocess.env.MYVAR) at run time nor are explorable via text search by their names from .env files within the built application's JS bundle.
You can still use original Vue CLI solution along;
For this use dotenv-webpack plugin in your vue.config.js as follows:
const Dotenv = require('dotenv-webpack');
const envPath = function() {
return (!process.env.NODE_ENV || (process.env.NODE_ENV === 'development')) ?
'./.env' :
`./.env.${process.env.NODE_ENV}`;
}
const dotenvArgs = {
expand: true,
path: envPath()
};
module.exports = {
//... some other config here
configureWebpack: {
plugins: [
new Dotenv(dotenvArgs)
]
}
};
Here:
expand: true allows for ${MYVAR} variables expansion;
path: envPath() allows to define custom .env file name depending on your Vue CLI project environments, and the path depending on you project structure;
There are other useful dotenv-webpack options you could use.
I believe this solution is good enough to fully satisfy most frequent use cases.
NB: Remember as you pass your secret variables set via .env into HTTP requests from your front-end (e.g. an API key in a call to some external API) they are visible to any one who knows where to look. To diminish security risks for this situation there are different solutions.
Just to hint you have either to:
provide only publicly open data via your application;
or authenticate your application (or parts of it) via some authentication service (login/password + JWT|sessions, external authentication providers e.g. Facebook, Google etc.);
or resort to server-generated application.
But this is the whole separate subject.
if you are cominng from VUE-cli-2 or you just cloned/installed an old vuejs project and you can't find .env file, this article explains what you have to do to set your .env variables as they environment files are probably located in config/dev.env.js (Note: this is peculiar to Vue-cli-2 files)
Here is also a solution and a detailed explanation for Vue-cli-3 .env related issue
What worked for me was changing from .env to .env.local. Haven't investigated WHY but I checked an old project and saw that I had a .env.local instead and did same for this project that would not pick the values from .env irrespective of whether vars where prefixed with VUE_APP and it worked.
It seems environment variables are not accessible in child Vue components. Best to declare them globally in main.js with Vue.prototype.env = process.env;
I know that this question was asked about vue-cli 3, which generates code for Vue 2. But it is the top result if you google for "vue3 does not embed env" and similar queries, so I assume that a lot of people end up here when having trouble with process.env variables being undefined in their Vue 3 app.
So this is an answer about how to fix your Vue 3 env issues.
This is what causes the confusion
If you google for env problems with vue, you end up in the vue-cli docs. But vue-cli was replaced by create-vue in Vue 3. There is a alert box at the top of the page that tells you this, but you've probably missed it.
If you did not miss it and followed one of the two links in the box, you ended up in the Vue 3 tooling guide or in the create-vue repo. None of those resources mention env variables. But you learn that create-vue is based on Vite.
If you follow that lead and google for "vite env", you end up in the vite documentation, where you finally find the answer:
env variables have to be prefixed with VITE_ to be compiled into the app (as opposed to VUE_APP_ in vue 2)
env variables will be available in import.meta.env in your app (as opposed to process.env in vue 2)
The latter one is what took me the longest to figure out.
This is how you need to do it
in an .env file in your project root:
VITE_MY_ENV_VAR=foo
The docs will also tell you about the different naming patterns for .env files in Vite. Very useful information if you work with different environments!
in your app:
const my_env_var = import.meta.env.VITE_MY_ENV_VAR
I hope this saves someone the time for figuring this out.
It might also help: make sure your .env files are in lowercase letters because in Linux it won't work even if it is working in windows
The answer provided here helped me out. I'm using Laravel with an odd setup for Vue 2.x. The project is also using Laravel Mix. Here's the solution:
Inside of your .env file, which is a sibling of package.json:
MY_ENVIRONMENT_VARIABLE=my_value
Inside of webpack.mix.js:
const { mix } = require('laravel-mix');
mix.webpackConfig(webpack => {
return {
plugins: [
new webpack.EnvironmentPlugin (
['MY_ENVIRONMENT_VARIABLE']
)
]
};
});
Afterwards, an npm run dev or npx mix should allow you to use these variables.
Credit: Thorsten LĂĽnborg

Using secret api keys on travis-ci

I'd like to use travis-ci for one of my projects.
The project is an API wrapper, so many of the tests rely on the use of secret API keys. To test locally, I just store them as environment variables. What's a safe way to use those keys on Travis?
Travis has a feature to encrypt environment variables ("Encrypting environment variables"). This can be used to protect your secret API keys. I've successfully used this for my Heroku API key.
All you have to do is install the travis gem, encrypt the string you want and add the encrypted string in your .travis.yml. The encryption is only valid for one repository. The travis command gets your public key for your repo and can then decrypt the string during the build.
gem install --user travis
travis encrypt MY_SECRET_ENV=super_secret -r my_username/my_repo
This gives you the following output:
Please add the following to your .travis.yml file:
secure: "OrEeqU0z6GJdC6Sx/XI7AMiQ8NM9GwPpZkVDq6cBHcD6OlSppkSwm6JvopTR\newLDTdtbk/dxKurUzwTeRbplIEe9DiyVDCzEiJGfgfq7woh+GRo+q6+UIWLE\n3nowpI9AzXt7iBhoKhV9lJ1MROrnn4DnlKxAEUlHTDi4Wk8Ei/g="
according to this in travis ci documentation it's said that :
If you have both the Heroku and Travis CI command line clients installed, you can get your key, encrypt it and add it to your .travis.yml by running the following command from your project directory:
travis encrypt $(heroku auth:token) --add deploy.api_key
refer to the following tutorial to install heroku client according to your OS
You can also define secret variables in repository settings:
Variables defined in repository settings are the same for all builds, and when you restart an old build, it uses the latest values. These variables are not automatically available to forks.
Define variables in the Repository Settings that:
differ per repository.
contain sensitive data, such as third-party credentials.
To define variables in Repository Settings, make sure you’re logged in, navigate to the repository in question, choose “Settings” from the cog menu, and click on “Add new variable” in the “Environment Variables” section.
Use a different set of API keys and do it the same way. Your travis box gets setup for your build run and then completely torn down again after your build has finished. You have root access to your box during the build, so you can do whatever you want with it.