Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: JWT_SECRET by default and enforcing a strong secret in production #35

Open
aichbauer opened this issue May 15, 2019 · 0 comments
Open

Comments

@aichbauer
Copy link
Owner

We should let the user know if they use a unsafe JWT_SECRET when they are not using production. jsonwebtoken uses HS256 as algorithmen, I read an article that it is possible to actually brute force the secret of a HS256 algorithm when using a "bad" secret. Actually one should use a 256 bit secret. which is the equivalent of 32 charcaters, since 1 char is 8 bit.

It would be better to actually throw when using NODE_ENV=production and not using a strong secret. Also it would be good to let the user know if they are using a "good" secret.

I would recommend something similar to:

// api/services/production.service.js
const productionService = () => {
  if (
    process.env.NODE_ENV
    // we have to choose a strong secret
    && process.env.JWT_SECRET
    && process.env.DB_NAME
    && process.env.DB_USER
    && process.env.DB_USER
    && process.env.DB_PASS
  ) {
    if (process.env.JWT_SECRET.length <= 31) {
      throw new Error('Not safe for production: JWT_SECRET should be at least 256 bit, e.g. 32 characters long');
    }

    return true;
  }

  throw new Error('Not safe for production: you forgot to set one or more environment variables');
};

module.exports = productionService;
// api/services/auth.service.js
const jwt = require('jsonwebtoken');

const productionService = require('./production.service');

const safeSecret = process.env.JWT_SECRET ? process.env.JWT_SECRET.length >= 32 : true;

const secret = () => {
  if (
    (
        safeSecret
        && process.env.JWT_SECRET
    )
    || 
    (
      process.env.NODE_ENV === 'production'
      && productionService()
    )
  ) {
    return process.env.JWT_SECRET;
  }

  if (
        !safeSecret
        && process.env.JWT_SECRET
    ) {
    console.error('\n\n\nYou are using a JWT_SECRET that would not be safe for production. Keep in mind that your secret should be at least 256 bit, e.g. 32 characters long.\n\n\n')
    return process.env.JWT_SECRET;
  }

  return 'secret';
};

const mySecret = secret();

const authService = () => {
  const issue = (payload) => jwt.sign(payload, mySecret, { expiresIn: 10800 });
  const verify = (token, cb) => jwt.verify(token, mySecret, {}, cb);

  return {
    issue,
    verify,
  };
};

module.exports = authService;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant