diff --git a/lib/utils/scope-util.js b/lib/utils/scope-util.js index e06a157..a067fdc 100644 --- a/lib/utils/scope-util.js +++ b/lib/utils/scope-util.js @@ -1,18 +1,25 @@ const isFormat = require('@node-oauth/formats'); const InvalidScopeError = require('../errors/invalid-scope-error'); +const whiteSpace = /\s+/g; module.exports = { parseScope: function (requestedScope) { - // XXX: isFormat.nqschar will trat Arrays of strings like String, - // thus we additionally check, whether incoming scopes are Arrays - if (!isFormat.nqschar(requestedScope) || Array.isArray(requestedScope)) { + if (requestedScope == null) { + return undefined; + } + + if (typeof requestedScope !== 'string') { throw new InvalidScopeError('Invalid parameter: `scope`'); } - if (requestedScope == null) { - return undefined; + // XXX: this prevents spaced-only strings to become + // treated as valid nqchar by making them empty strings + requestedScope = requestedScope.trim(); + + if(!isFormat.nqschar(requestedScope)) { + throw new InvalidScopeError('Invalid parameter: `scope`'); } - return requestedScope.split(' '); + return requestedScope.split(whiteSpace); } }; diff --git a/test/unit/utils/scope-util_test.js b/test/unit/utils/scope-util_test.js new file mode 100644 index 0000000..505262f --- /dev/null +++ b/test/unit/utils/scope-util_test.js @@ -0,0 +1,45 @@ +const { parseScope } = require('../../../lib/utils/scope-util'); +const should = require('chai').should(); + +describe(parseScope.name, () => { + it('should return undefined on nullish values', () => { + const values = [undefined, null]; + values.forEach(str => { + const compare = parseScope(str) === undefined; + compare.should.equal(true); + }); + }); + it('should throw on non-string values', () => { + const invalid = [1, -1, true, false, {}, ['foo'], [], () => {}, Symbol('foo')]; + invalid.forEach(str => { + try { + parseScope(str); + should.fail(); + } catch (e) { + e.message.should.eql('Invalid parameter: `scope`'); + } + }); + }); + it('should throw on empty strings', () => { + const invalid = ['', ' ', ' ', '\n', '\t', '\r']; + invalid.forEach(str => { + try { + parseScope(str); + should.fail(); + } catch (e) { + e.message.should.eql('Invalid parameter: `scope`'); + } + }); + }); + it('should split space-delimited strings into arrays', () => { + const values = [ + ['foo', ['foo']], + ['foo bar', ['foo', 'bar']], + ['foo bar', ['foo', 'bar']], + ]; + values.forEach(([str, compare]) => { + const parsed = parseScope(str); + parsed.should.deep.equal(compare); + }); + }); +}); \ No newline at end of file