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

Fix cryptographically insecure ID generation #116

Merged
merged 18 commits into from
Feb 10, 2021
Merged

Fix cryptographically insecure ID generation #116

merged 18 commits into from
Feb 10, 2021

Conversation

tomauth0
Copy link
Contributor

@tomauth0 tomauth0 commented Jan 25, 2021

Description

The existing methods of ID generation are not cryptographically secure. This PR introduces the id-generation lib - a lightweight lib for generating suitably random IDs with a given dictionary. Utils.js updated to make use of this lib

Also used the opportunity to cleanup some of the utils file - swapping out vars and removing some unneeded syntax

References

#111

Testing

Unit tests added for ID length and dictionary memebership

  • This change adds test coverage for new/changed/fixed functionality

Checklist

  • I have added documentation for new/changed functionality in this PR or in auth0.com/docs
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not master

@tomauth0 tomauth0 changed the title chore: Id generation Fix cryptographically insecure ID generation Jan 29, 2021
Copy link
Contributor

@jakelacey2012 jakelacey2012 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I'd have a go at reviewing some code today, let me know what you think of my comments. I don't think I'm comfortable yet in hitting the approve button, so might be best to get another pair of eyes as well :)

});
});
describe('generateUniqueID', function() {
it('should generate an ID from the alphabet', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it('should generate an ID from the alphabet', function() {
it('should generate an ID including characters from 0 to 9 and the alphabet', function() {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, in this case the 'alphabet' refers to an 'alphabet' parameter on the ID Gen library, as opposed to the english alphabet - it tests that the characters in the resulting ID intersect with the chars passed in the alphabet param on IdGenerator creation


if (input[0] === 60) { // open tag
// content is just encoded, not zipped
var xml = new xmldom.DOMParser().parseFromString(input.toString());
const xml = new xmldom.DOMParser().parseFromString(input.toString());
if (!xml || !xml.documentElement) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this bit of code is the same in the else statement the only difference is that we're unzipping it, I wonder if this bit of code could be abstracted into a function which is passed the result of .toString().

const xml = new xmldom.DOMParser().parseFromString(input);

if (!xml || !xml.documentElement) {
   return callback(new Error('Invalid SAML Request'));
}

configureSigningCredentials(xml, function (err, shouldValidate) {
   if (!shouldValidate) {
          return callback(null, xml);
   }
   checkSignature(xml, callback);
});

I think doing this should mean we can avoid setting xml = null in the next block as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted. I usually "lift" the optional computation into a local const to keep the computation linear.

const input = new Buffer(samlRequest, 'base64');
const inflateIfNeeded = input[0] === 60 ? (cb) => setImmediate(cb, null, input) : zlib.inflateRaw;

inflateIfNeeded(input, function(err, inflated) {
  // shared logic
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats nice, I think I prefer that way!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great spot and change, but I'm apprehensive to apply it in this particular PR & ticket.
There's a few different areas in the utils file (and across the lib) that could do with a refactor (misspelled opts, etc.). I'll place a ticket on the backlog that references this suggestion and a few other proposals.

Copy link
Contributor

@jakelacey2012 jakelacey2012 Feb 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds sensible to me. :)


if (input[0] === 60) { // open tag
// content is just encoded, not zipped
var xml = new xmldom.DOMParser().parseFromString(input.toString());
const xml = new xmldom.DOMParser().parseFromString(input.toString());
if (!xml || !xml.documentElement) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted. I usually "lift" the optional computation into a local const to keep the computation linear.

const input = new Buffer(samlRequest, 'base64');
const inflateIfNeeded = input[0] === 60 ? (cb) => setImmediate(cb, null, input) : zlib.inflateRaw;

inflateIfNeeded(input, function(err, inflated) {
  // shared logic
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants