New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

oniyi-http-plugin-credentials

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

oniyi-http-plugin-credentials - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

91

lib/index.js

@@ -14,2 +14,3 @@ 'use strict';

const PLUGIN_NAME = 'attach-credentials';
const REQUEST_PHASE_NAME = 'credentials';

@@ -46,59 +47,67 @@ const defaults = {

const extractRequestparams = makeRequestParamsExtractor(removeUserProp, userPropName);
const extractRequestParams = makeRequestParamsExtractor(removeUserProp, userPropName);
return {
name: PLUGIN_NAME,
load: (req, origParams, callback) => {
// create a copy of provided request parameters (remove user prop if requested in `options`)
const reqParams = extractRequestparams(origParams);
const { [userPropName]: user } = origParams;
onRequest: [{
phaseName: REQUEST_PHASE_NAME,
handler: (ctx, next) => {
const { options } = ctx;
// create a copy of provided request parameters (remove user prop if requested in `options`)
const reqParams = extractRequestParams(options);
const { [userPropName]: user } = options;
if (!user) {
debug('No "%s" prop found in request params, skipping plugin operations', userPropName, origParams);
// [bk] @TODO: should we use `reqParams` here instead?
// That would mean we potentially pass back params without
// the user prop and without credentials
callback(null, origParams);
return;
}
if (!user) {
debug('Reason: No "%s" prop found in request options', userPropName, options);
if (!_.isFunction(user[credentialsMethodName])) {
const msg = `${userPropName}.${credentialsMethodName} must be a function`;
debug(msg, { user });
callback(new TypeError(msg));
return;
}
user[credentialsMethodName](providerName, reqParams, (getCredentialsError, credentials) => {
if (getCredentialsError) {
debug(
'Failed to load credentials for %s %s and provider %s',
userPropName,
getUserId(user),
providerName,
getCredentialsError
);
callback(getCredentialsError);
// This would mean we potentially pass back params without
// the user prop and without credentials
next();
return;
}
if (!credentials) {
// [bk] @TODO: add switch to plugin options to either abort or ignore this error.
// currently we abort
const err = new Error(`No credentials found for user "${getUserId(user)}" and provider "${providerName}"`);
debug(err.message);
callback(err);
if (!_.isFunction(user[credentialsMethodName])) {
const msg = `${userPropName}.${credentialsMethodName} must be a function`;
debug(msg, { user });
next(new TypeError(msg));
return;
}
applyCredentials(reqParams, credentials, (applyCredentialsError, reqParamsWithCredentials) => {
if (applyCredentialsError) {
callback(applyCredentialsError);
user[credentialsMethodName](providerName, reqParams, (getCredentialsError, credentials) => {
if (getCredentialsError) {
debug(
'Failed to load credentials for %s %s and provider %s',
userPropName,
getUserId(user),
providerName,
getCredentialsError
);
next(getCredentialsError);
return;
}
callback(null, reqParamsWithCredentials);
if (!credentials) {
// [bk] @TODO: add switch to plugin options to either abort or ignore this error.
// currently we abort
const err = new Error(`No credentials found for user "${getUserId(user)}" and provider "${providerName}"`);
debug(err.message);
next(err);
return;
}
applyCredentials(reqParams, credentials, (applyCredentialsError, reqParamsWithCredentials) => {
if (applyCredentialsError) {
next(applyCredentialsError);
return;
}
// once we acquired request params with credentials, need to update current ctx.options
// so that next phase hook handler can use them as well
_.assign(ctx, { options: reqParamsWithCredentials });
next();
});
});
});
}
},
],
};
};
{
"name": "oniyi-http-plugin-credentials",
"version": "1.0.0",
"version": "1.1.0",
"description": "A plugin for oniyi-http-client for automatic attachment of user credentials",

@@ -26,3 +26,3 @@ "homepage": "https://github.com/benkroeger/oniyi-http-plugin-credentials#readme",

"devDependencies": {
"ava": " ^0.23.0",
"ava": " ^0.25.0",
"eslint": "^4.10.0",

@@ -29,0 +29,0 @@ "eslint-config-oniyi": "^5.0.2",

# oniyi-http-plugin-credentials [![NPM version][npm-image]][npm-url] [![Dependency Status][daviddm-image]][daviddm-url]
> An async plugin for oniyi-http-client to resolve and attach credentials to request params
This plugin is designed to work with the [third-party login component](https://docs.strongloop.com/pages/releaseview.action?pageId=3836277) of [loopback](https://docs.strongloop.com/display/public/LB/LoopBack).
The [third-party login component](https://docs.strongloop.com/pages/releaseview.action?pageId=3836277) is heavily based on [passportjs](http://passportjs.org/).
To make things work more broadly, I also wrote a [loopback](https://docs.strongloop.com/display/public/LB/LoopBack) extension to allow the usage of custom auth schemes [oniyi-loopback-passport-custom-schemes](https://github.com/benkroeger/oniyi-loopback-passport-custom-schemes).
resolve endpoint specific credentials asynchronusly and inject them into request options before making the actual request to endpoint

@@ -20,4 +18,5 @@ ## Installation

const clientOptions = {};
const httpClient = new OniyiHttpClient(clientOptions);
const httpClientParams = {
requestPhases: ['initial','credentials', 'final'],
};

@@ -31,4 +30,14 @@ const pluginOptions = {

const plugin = oniyiHttpPluginCredentials(pluginOptions);
const phaseMapOptions = {
requestPhaseMap: {
credentials: 'newCredentialsPhase',
},
responsePhaseMap: {
final: 'end',
},
};
httpClient.use(plugin);
const httpClient = OniyiHttpClient
.create(httpClientParams) // create custom http client with defined phase lists
.use(plugin, phaseMapOptions); // mount a plugin
```

@@ -47,15 +56,18 @@

`plugin.load()` retrieves an object with parameters (origParams) that will later be used to make an http(s) request. From there, the following flow is applied:
This plugin relies on logic implemented in [oniyi-http-client](https://npmjs.org/package/oniyi-http-client), which has extensive documentation on how phase lists work and what conventions must be followed when implementing a plugin.
Basically, we have implemented a phase list hook handler which gets invoked in `request phase list` of http client.
Once `credentials` hook handler gets invoked, it receives a `ctx` and `next` params. Once we pull `options` from the context object, the following flow is applied:
copy `origParams` into `reqParams`. Depending on `options.removeUserProp`, the original prop named `options.userPropName` will be omitted or included.
read prop named `options.userPropName` from `origParams` into `user`.
If `user` can not be found, abort flow and invoke callback with `origParams`.
If `user[options.credentialsMethodName]` is not a function, invoke callback with `Error`.
copy `options` into `reqParams`. Depending on `pluginOptions.removeUserProp`, the original prop named `pluginOptions.userPropName` will be omitted or included.
read prop named `pluginOptions.userPropName` from `options` into `user`.
If `user` can not be found, abort flow and invoke `next` function so that next plugin in this phase list can do its operations.
If `user[pluginOptions.credentialsMethodName]` is not a function, invoke `next` with `Error`.
Invoke `user[options.credentialsMethodName]` with `options.providerName` and `reqParams` as well as a callback function.
Now `user[options.credentialsMethodName]` is supposed to resolve credentials for `user` and the authentication provider. This resolution should happen async and results be passed to our local callback (which takes `err` and `credentials` arguments).
Invoke `user[pluginOptions.credentialsMethodName]` with `pluginOptions.providerName` and `reqParams` as well as a callback function.
Now `user[pluginOptions.credentialsMethodName]` is supposed to resolve credentials for `user` and the authentication provider. This resolution should happen async and results be passed to our local callback (which takes `err` and `credentials` arguments).
If an error occurs, plugin flow is aborted and `err` passed to callback.
If `credentials` is falsy, plugin flow is also aborted and callback invoked with an according error.
If `credentials` is falsy, plugin flow is also aborted and `next` gets invoked.
At this point, we let `user[options.credentialsMethodName]` resolve credentials for the auth provider that this plugin instance is configured for – and no errors occurred.
At this point, we let `user[pluginOptions.credentialsMethodName]` resolve credentials for the auth provider that this plugin instance is configured for – and no errors occurred.

@@ -65,2 +77,3 @@ Now the plugin applies `credentials` to `reqParams`. For that, `credentials.type` is mapped against a list of supported credential types. If `credentials.type` is supported, that type specific implementation is invoked with `reqParams` and `credentials.payload`.

Finally, we update the `ctx.options` object with latest `reqParamsWithCredentials` changes, and invoke `next` function.

@@ -67,0 +80,0 @@ ## Credentials types

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc