Skip to content

Commit

Permalink
refactor: removes lodash
Browse files Browse the repository at this point in the history
closes #272
  • Loading branch information
panva committed Jun 26, 2020
1 parent aa64611 commit 7bc9b91
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 41 deletions.
47 changes: 21 additions & 26 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ const url = require('url');
const { ParseError } = require('got');
const jose = require('jose');
const base64url = require('base64url');
const defaultsDeep = require('lodash/defaultsDeep');
const defaults = require('lodash/defaults');
const merge = require('lodash/merge');
const isPlainObject = require('lodash/isPlainObject');
const tokenHash = require('oidc-token-hash');

const defaults = require('./helpers/defaults');
const { assertSigningAlgValuesSupport, assertIssuerConfiguration } = require('./helpers/assert');
const pick = require('./helpers/pick');
const isPlainObject = require('./helpers/is_plain_object');
const processResponse = require('./helpers/process_response');
const TokenSet = require('./token_set');
const { OPError, RPError } = require('./errors');
Expand All @@ -32,6 +30,8 @@ const instance = require('./helpers/weak_cache');
const { authenticatedPost, resolveResponseType, resolveRedirectUri } = require('./helpers/client');
const DeviceFlowHandle = require('./device_flow_handle');

const { deep: defaultsDeep } = defaults;

function pickCb(input) {
return pick(input, ...CALLBACK_PROPERTIES);
}
Expand Down Expand Up @@ -1488,26 +1488,21 @@ module.exports = (issuer, aadIssValidation = false) => class Client extends Base
* @name requestObject
* @api public
*/
async requestObject(requestObject = {}, algorithms = {}) {
async requestObject(requestObject = {}, {
sign: signingAlgorithm = this.request_object_signing_alg || 'none',
encrypt: {
alg: eKeyManagement = this.request_object_encryption_alg,
enc: eContentEncryption = this.request_object_encryption_enc || 'A128CBC-HS256',
} = {},
} = {}) {
if (!isPlainObject(requestObject)) {
throw new TypeError('requestObject must be a plain object');
}

defaults(algorithms, {
sign: this.request_object_signing_alg,
encrypt: {
alg: this.request_object_encryption_alg,
enc: this.request_object_encryption_enc || 'A128CBC-HS256',
},
}, {
sign: 'none',
});

let signed;
let key;

const alg = algorithms.sign;
const header = { alg, typ: 'JWT' };
const header = { alg: signingAlgorithm, typ: 'JWT' };
const payload = JSON.stringify(defaults({}, requestObject, {
iss: this.client_id,
aud: this.issuer.issuer,
Expand All @@ -1517,25 +1512,25 @@ module.exports = (issuer, aadIssValidation = false) => class Client extends Base
exp: now() + 300,
}));

if (alg === 'none') {
if (signingAlgorithm === 'none') {
signed = [
base64url.encode(JSON.stringify(header)),
base64url.encode(payload),
'',
].join('.');
} else {
const symmetric = alg.startsWith('HS');
const symmetric = signingAlgorithm.startsWith('HS');
if (symmetric) {
key = await this.joseSecret();
} else {
const keystore = instance(this).get('keystore');

if (!keystore) {
throw new TypeError(`no keystore present for client, cannot sign using alg ${alg}`);
throw new TypeError(`no keystore present for client, cannot sign using alg ${signingAlgorithm}`);
}
key = keystore.get({ alg, use: 'sig' });
key = keystore.get({ alg: signingAlgorithm, use: 'sig' });
if (!key) {
throw new TypeError(`no key to sign with found for alg ${alg}`);
throw new TypeError(`no key to sign with found for alg ${signingAlgorithm}`);
}
}

Expand All @@ -1545,11 +1540,11 @@ module.exports = (issuer, aadIssValidation = false) => class Client extends Base
});
}

if (!algorithms.encrypt.alg) {
if (!eKeyManagement) {
return signed;
}

const fields = { alg: algorithms.encrypt.alg, enc: algorithms.encrypt.enc, cty: 'JWT' };
const fields = { alg: eKeyManagement, enc: eContentEncryption, cty: 'JWT' };

if (fields.alg.match(/^(RSA|ECDH)/)) {
[key] = await this.issuer.queryKeyStore({
Expand Down Expand Up @@ -1599,10 +1594,10 @@ BaseClient.prototype.resource = deprecate(
/* istanbul ignore next */
async function resource(resourceUrl, accessToken, options) {
let token = accessToken;
const opts = merge({
const opts = defaultsDeep({}, options, {
verb: 'GET',
via: 'header',
}, options);
});

if (token instanceof TokenSet) {
if (!token.access_token) {
Expand Down
5 changes: 2 additions & 3 deletions lib/errors.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable camelcase */
const { format } = require('util');

const assign = require('lodash/assign');
const makeError = require('make-error');

function OPError({
Expand All @@ -14,7 +13,7 @@ function OPError({
}, response) {
OPError.super.call(this, !error_description ? error : `${error} (${error_description})`);

assign(
Object.assign(
this,
{ error },
(error_description && { error_description }),
Expand Down Expand Up @@ -45,7 +44,7 @@ function RPError(...args) {
} else {
RPError.super.call(this, message);
}
assign(this, rest);
Object.assign(this, rest);
if (response) {
Object.defineProperty(this, 'response', {
value: response,
Expand Down
11 changes: 7 additions & 4 deletions lib/helpers/client.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
const merge = require('lodash/merge');
const omitBy = require('lodash/omitBy');
const jose = require('jose');

const { assertIssuerConfiguration } = require('./assert');
const { random } = require('./generators');
const now = require('./unix_timestamp');
const request = require('./request');
const instance = require('./weak_cache');
const { deep: defaultsDeep } = require('./defaults');

const formUrlEncode = (value) => encodeURIComponent(value).replace(/%20/g, '+');

Expand Down Expand Up @@ -126,7 +125,7 @@ async function authenticatedPost(endpoint, opts, {
clientAssertionPayload, endpointAuthMethod = endpoint,
} = {}) {
const auth = await authFor.call(this, endpointAuthMethod, { clientAssertionPayload });
const requestOpts = merge(opts, auth, { form: true });
const requestOpts = defaultsDeep({ form: true }, auth, opts);

const mTLS = this[`${endpointAuthMethod}_endpoint_auth_method`].includes('tls_client_auth')
|| (endpoint === 'token' && this.tls_client_certificate_bound_access_tokens);
Expand All @@ -139,7 +138,11 @@ async function authenticatedPost(endpoint, opts, {
targetUrl = targetUrl || this.issuer[`${endpoint}_endpoint`];

if ('body' in requestOpts) {
requestOpts.body = omitBy(requestOpts.body, (arg) => arg === undefined);
for (const [key, value] of Object.entries(requestOpts.body)) { // eslint-disable-line no-restricted-syntax, max-len
if (typeof value === 'undefined') {
delete requestOpts.body[key];
}
}
}

return request.call(this, {
Expand Down
1 change: 1 addition & 0 deletions lib/helpers/deep_clone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = (obj) => JSON.parse(JSON.stringify(obj));
25 changes: 25 additions & 0 deletions lib/helpers/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* eslint-disable no-restricted-syntax */

const isPlainObject = require('./is_plain_object');

function defaults(deep, target, ...sources) {
for (const source of sources) {
if (!isPlainObject(source)) {
continue; // eslint-disable-line no-continue
}
for (const [key, value] of Object.entries(source)) {
if (typeof target[key] === 'undefined' && typeof value !== 'undefined') {
target[key] = value;
}

if (deep && isPlainObject(target[key]) && isPlainObject(value)) {
defaults(true, target[key], value);
}
}
}

return target;
}

module.exports = defaults.bind(undefined, false);
module.exports.deep = defaults.bind(undefined, true);
1 change: 1 addition & 0 deletions lib/helpers/is_plain_object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = (a) => !!a && a.constructor === Object;
6 changes: 3 additions & 3 deletions lib/helpers/request.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
const Got = require('got');
const defaultsDeep = require('lodash/defaultsDeep');

const pkg = require('../../package.json');

const { deep: defaultsDeep } = require('./defaults');
const isAbsoluteUrl = require('./is_absolute_url');
const { HTTP_OPTIONS } = require('./consts');

let DEFAULT_HTTP_OPTIONS;
let got;

const setDefaults = (options) => {
DEFAULT_HTTP_OPTIONS = defaultsDeep(options, DEFAULT_HTTP_OPTIONS);
DEFAULT_HTTP_OPTIONS = defaultsDeep({}, options, DEFAULT_HTTP_OPTIONS);
got = Got.extend(DEFAULT_HTTP_OPTIONS);
};

Expand All @@ -28,7 +28,7 @@ module.exports = function request(options, { mTLS = false } = {}) {
const optsFn = this[HTTP_OPTIONS];
let opts;
if (optsFn) {
opts = optsFn.call(this, defaultsDeep(options, DEFAULT_HTTP_OPTIONS));
opts = optsFn.call(this, defaultsDeep({}, options, DEFAULT_HTTP_OPTIONS));
} else {
opts = options;
}
Expand Down
3 changes: 1 addition & 2 deletions lib/passport_strategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
const url = require('url');
const { format } = require('util');

const cloneDeep = require('lodash/cloneDeep');

const cloneDeep = require('./helpers/deep_clone');
const { RPError, OPError } = require('./errors');
const { BaseClient } = require('./client');
const { random, codeChallenge } = require('./helpers/generators');
Expand Down
3 changes: 1 addition & 2 deletions lib/token_set.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const base64url = require('base64url');
const assign = require('lodash/assign');

const now = require('./helpers/unix_timestamp');

Expand All @@ -9,7 +8,7 @@ class TokenSet {
* @api public
*/
constructor(values) {
assign(this, values);
Object.assign(this, values);
}

/**
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
"base64url": "^3.0.1",
"got": "^9.6.0",
"jose": "^1.27.1",
"lodash": "^4.17.15",
"lru-cache": "^5.1.1",
"make-error": "^1.3.6",
"object-hash": "^2.0.1",
Expand Down

0 comments on commit 7bc9b91

Please sign in to comment.