Socket
Socket
Sign inDemoInstall

@adobe/fetch

Package Overview
Dependencies
Maintainers
56
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@adobe/fetch - npm Package Compare versions

Comparing version 0.2.4 to 0.3.0

cra-fetch-test/node_modules/.cache/babel-loader/662942f518570731b65c8893e592e050.json

6

.eslintrc.js

@@ -19,3 +19,7 @@ /*

},
globals: {
fetch: "readonly",
localStorage: "readonly",
window: "readonly"
},
env: {

@@ -22,0 +26,0 @@ es6: true,

188

index.js

@@ -13,186 +13,12 @@ /*

const fetch = require('node-fetch');
const cache = require('./src/cache');
const uuid = require('uuid/v4');
const storage = require('./src/storage');
const auth = require('@adobe/jwt-auth');
const debug = require('debug')('@adobe/fetch');
const NO_CONFIG = 'Auth configuration missing.';
global.fetch = require('node-fetch');
const adobefetch = require('./src/adobefetch');
async function getToken(authOptions, tokenCache, forceNewToken) {
const key = authOptions.clientId + '|' + authOptions.metaScopes.join(',');
let token = await tokenCache.get(key);
if (token && !forceNewToken) {
return token;
} else {
try {
token = await auth(authOptions);
if (token) {
return tokenCache.set(key, token);
} else {
throw 'Access token empty';
}
} catch (err) {
console.error('Error while getting a new access token.', err);
throw err;
}
}
}
function capFirst(s) {
return s[0].toUpperCase() + s.slice(1);
}
function generateRequestID() {
return uuid().replace(/-/g, '');
}
function normalizeHeaders(headers) {
let normalized = {};
if (headers) {
if (typeof headers.entries === 'function') {
// This is a headers object, iterate with for..of.
for (let pair of headers.entries()) {
const [name, value] = pair;
normalized[name.toLowerCase()] = value;
}
} else {
// This is a normal JSON. Iterate with for.. in
for (let name in headers) {
normalized[name.toLowerCase()] = headers[name];
}
}
}
return normalized;
}
function calculateHeaders(predefinedHeaders) {
let headers = {};
for (let name in predefinedHeaders) {
const value = predefinedHeaders[name];
if (typeof value === 'function') {
headers[name] = value();
} else {
headers[name] = value;
}
}
return headers;
}
function getHeaders(token, options, predefinedHeaders) {
let headers = calculateHeaders(predefinedHeaders);
if (options && options.headers) {
headers = Object.assign(headers, normalizeHeaders(options.headers));
}
headers.authorization = `${capFirst(token.token_type)} ${token.access_token}`;
return headers;
}
async function _fetch(url, opts, configOptions, tokenCache, forceNewToken) {
const token = await getToken(configOptions.auth, tokenCache, forceNewToken);
const fetchOpts = Object.assign({}, opts);
fetchOpts.headers = getHeaders(token, opts, configOptions.headers);
debug(
`${fetchOpts.method || 'GET'} ${url} - x-request-id: ${
fetchOpts.headers['x-request-id']
}`
);
const res = await fetch(url, fetchOpts);
if (!res.ok) {
debug(
`${fetchOpts.method || 'GET'} ${url} - status ${res.statusText} (${
res.status
}). x-request-id: ${fetchOpts.headers['x-request-id']}`
);
if ((res.status === 401 || res.status === 403) && !forceNewToken) {
debug(`${opts.method || 'GET'} ${url} - Will get new token.`);
return await _fetch(url, opts, configOptions, tokenCache, true);
}
}
return res;
}
/**
* Fetch function
*
* @return Promise
* @param url
* @param options
*/
function adobefetch(url, options, configOptions, tokenCache) {
return _fetch(url, options, configOptions, tokenCache, false);
}
function verifyConfig(options) {
let {
clientId,
technicalAccountId,
orgId,
clientSecret,
privateKey,
metaScopes,
storage
} = options;
const errors = [];
!clientId ? errors.push('clientId') : '';
!technicalAccountId ? errors.push('technicalAccountId') : '';
!orgId ? errors.push('orgId') : '';
!clientSecret ? errors.push('clientSecret') : '';
!privateKey ? errors.push('privateKey') : '';
!metaScopes || metaScopes.length === 0 ? errors.push('metaScopes') : '';
if (errors.length > 0) {
throw `Required parameter(s) ${errors.join(', ')} are missing`;
}
if (
!(
typeof privateKey === 'string' ||
privateKey instanceof Buffer ||
ArrayBuffer.isView(privateKey)
)
) {
throw 'Required parameter privateKey is invalid';
}
if (storage) {
let { read, write } = storage;
if (!read) {
throw 'Storage read method missing!';
} else if (!write) {
throw 'Storage write method missing!';
}
}
}
function config(configOptions) {
if (!configOptions.auth) {
throw NO_CONFIG;
} else {
verifyConfig(configOptions.auth);
}
const tokenCache = cache.config(configOptions.auth);
configOptions.headers = Object.assign(
{
'x-api-key': configOptions.auth.clientId,
'x-request-id': () => generateRequestID(),
'x-gw-ims-org-id': configOptions.auth.orgId
},
normalizeHeaders(configOptions.headers)
);
return (url, options = {}) =>
adobefetch(url, options, configOptions, tokenCache);
}
module.exports = {
config: config,
normalizeHeaders: normalizeHeaders,
generateRequestID: generateRequestID
config: adobefetch.getConfig(storage, auth),
normalizeHeaders: adobefetch.normalizeHeaders,
generateRequestID: adobefetch.generateRequestID,
AUTH_MODES: adobefetch.AUTH_MODES
};
{
"name": "@adobe/fetch",
"version": "0.2.4",
"version": "0.3.0",
"description": "Call Adobe APIs",
"main": "index.js",
"main": "dist/server.js",
"browser": "dist/client.js",
"repository": {

@@ -17,5 +18,5 @@ "type": "git",

"scripts": {
"lint": "eslint src test sample index.js",
"run": "node index.js",
"test": "jest"
"lint": "eslint src test sample index*.js",
"test": "jest",
"build": "webpack"
},

@@ -37,3 +38,3 @@ "keywords": [

"debug": "^4.1.1",
"dotenv": "^8.1.0",
"dotenv": "^8.2.0",
"node-fetch": "^2.6.0",

@@ -45,6 +46,9 @@ "node-persist": "^3.0.5",

"eslint": "^6.6.0",
"eslint-config-prettier": "^6.5.0",
"eslint-config-prettier": "^6.7.0",
"eslint-plugin-prettier": "^3.1.1",
"jest": "^24.9.0",
"prettier": "^1.18.2"
"prettier": "^1.19.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-node-externals": "^1.7.2"
},

@@ -51,0 +55,0 @@ "jest": {

[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Version](https://img.shields.io/npm/v/@adobe/fetch.svg)](https://npmjs.org/package/@adobe/fetch)
[![Downloads/week](https://img.shields.io/npm/dw/@adobe/fetch.svg)](https://npmjs.org/package/@adobe/fetch)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Build Status](https://travis-ci.com/adobe/adobe-fetch.svg?branch=master)](https://travis-ci.com/adobe/adobe-fetch)
[![codecov](https://codecov.io/gh/adobe/adobe-fetch/branch/master/graph/badge.svg)](https://codecov.io/gh/adobe/adobe-fetch)
[![Greenkeeper badge](https://badges.greenkeeper.io/adobe/adobe-fetch.svg)](https://greenkeeper.io/)
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/adobe/adobe-fetch.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/adobe/adobe-fetch/context:javascript)

@@ -18,4 +18,6 @@ # adobe-fetch

This package will handle JWT authentication, token caching and storage.
Otherwise it works exactly as [fetch](https://github.com/bitinn/node-fetch)
Otherwise it works exactly as [fetch](https://github.com/bitinn/node-fetch).
This library now works in the browser as well, see information below.
### Installation

@@ -31,2 +33,3 @@

const AdobeFetch = require('@adobe/fetch');
const fs = require('fs');

@@ -46,3 +49,3 @@

const adobefetch = require('@adobe/fetch').config(config);
const adobefetch = AdobeFetch.config(config);

@@ -112,2 +115,47 @@ adobefetch("https://platform.adobe.io/some/adobe/api", { method: 'get'})

#### Alternative authentication methods
To use this library with an alternative authentication flow such as OAuth, or execute the JWT authentication flow outside of adobe-fetch, it is possible to use the **Provided** mode and provide the access token directly to adobe-fetch via an asynchronious function:
```javascript
const AdobeFetch = require('@adobe/fetch');
const { AUTH_MODES } = AdobeFetch;
const adobefetch = AdobeFetch).config({
auth: {
mode: AUTH_MODES.Provided,
clientId: 'asasdfasf',
orgId: 'asdfasdfasdf@AdobeOrg',
tokenProvider: async () => { ... Logic returning a valid access token object ... }
}
});
adobefetch("https://platform.adobe.io/some/adobe/api", { method: 'get'})
.then(response => response.json())
.then(json => console.log('Result: ',json));
```
When the **adobefetch** call above happens for the first time, it will call the tokenProvider function provided and wait for it to return the access token. Access token is then cached and persisted, if it expires or is rejected by the API, the tokenProvider function will be called again to acquire a new token.
A valid token has the following structure:
```
{
token_type: 'bearer',
access_token: <<<TOKEN>>>,
expires_in: <<<EXPIRY_IN_MILLISECONDS>>>
}
```
#### Using in the browser
In the browser only the **Provided** mode explained above is default, JWT is not supported.
This is because the JWT workflow requires direct access to the private key and should be done in the server for security reasons. With Provided mode the access token can be acquired via a standard OAuth authentication flow and then used by adobe-fetch to call Adobe APIs.
Using ```require('@adobe/fetch')``` in a web app will automatically use the browser version.
You can also include the [bundled JS](dist/client.js) file directly in a script tag.
#### Predefined Headers

@@ -114,0 +162,0 @@

@@ -30,5 +30,9 @@ /*

const AdobeFetch = require('../index.js');
const { AUTH_MODES } = AdobeFetch;
async function main() {
const adobefetch = require('../index.js').config({
const adobefetch = AdobeFetch.config({
auth: {
mode: AUTH_MODES.JWT,
clientId: process.env.APIKEY,

@@ -35,0 +39,0 @@ clientSecret: process.env.SECRET,

@@ -14,4 +14,2 @@ /* eslint-disable require-atomic-updates */

const storage = require('./storage');
// Consider a token expired 60 seconds before its calculated expiry time.

@@ -91,6 +89,8 @@ const EXPIRY_THRESHOLD = 60 * 1000;

function config(options) {
function config(options, defaultStorage) {
const disableStorage = (options && options.disableStorage) || false;
const readFunc = options.storage ? options.storage.read : storage.read;
const writeFunc = options.storage ? options.storage.write : storage.write;
const readFunc = options.storage ? options.storage.read : defaultStorage.read;
const writeFunc = options.storage
? options.storage.write
: defaultStorage.write;

@@ -97,0 +97,0 @@ const cache = {

@@ -21,3 +21,9 @@ /*

const TOKEN_KEY = `${CLIENT_ID}|${SCOPES.join(',')}`;
const TOKEN_PROVIDED_KEY = `${CLIENT_ID}|org-${ORG_ID}`;
const MOCK_URL = 'https://mock.com/mock';
const DEFAULT_TOKEN = {
token_type: 'bearer',
access_token: 'abcdef',
expires_in: 86399956
};

@@ -58,8 +64,19 @@ module.exports = {

},
providedConfig: {
mode: 'provided',
clientId: CLIENT_ID,
orgId: ORG_ID,
tokenProvider: async () => DEFAULT_TOKEN
},
customProvidedConfig: provider => {
return {
mode: 'provided',
clientId: CLIENT_ID,
orgId: ORG_ID,
tokenProvider: provider
};
},
token_key: TOKEN_KEY,
token: {
token_type: 'bearer',
access_token: 'abcdef',
expires_in: 86399956
},
token_provided_key: TOKEN_PROVIDED_KEY,
token: DEFAULT_TOKEN,
token2: {

@@ -76,2 +93,8 @@ token_type: 'bearer',

expires_at: Date.now() + 100000
},
[TOKEN_PROVIDED_KEY]: {
token_type: 'bearer',
access_token: 'abcabc',
expires_in: 86399956,
expires_at: Date.now() + 100000
}

@@ -78,0 +101,0 @@ },

@@ -16,4 +16,19 @@ /*

const adobefetch = require('../index');
const adobefetchBrowser = require('../index.client');
const mockData = require('./mockData');
const localStorageMock = (function() {
let store = {};
return {
getItem: key => store[key] || null,
setItem: (key, value) => (store[key] = value.toString()),
removeItem: key => delete store[key],
clear: () => (store = {})
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
jest.mock('@adobe/jwt-auth');

@@ -176,1 +191,43 @@ jest.mock('node-fetch');

});
describe('Validate local storage', () => {
test('reads from local storage', async () => {
expect.assertions(2);
const token = mockData.valid_token[mockData.token_provided_key];
fetch.mockImplementation((url, options) => {
expect(options.headers).toBeDefined();
expect(options.headers['authorization']).toBe(
`Bearer ${token.access_token}`
);
return Promise.resolve(mockData.responseOK);
});
window.localStorage.clear();
window.localStorage.setItem('tokens', JSON.stringify(mockData.valid_token));
await adobefetchBrowser.config({
auth: mockData.providedConfig
})(mockData.url);
});
test('write to local storage', async () => {
expect.assertions(1);
const token = mockData.valid_token[mockData.token_provided_key];
window.localStorage.clear();
fetch.mockImplementation(() => Promise.resolve(mockData.responseOK));
await adobefetchBrowser.config({
auth: mockData.customProvidedConfig(
() => mockData.valid_token[mockData.token_provided_key]
)
})(mockData.url);
const tokens = JSON.parse(window.localStorage.getItem('tokens'));
expect(tokens[mockData.token_provided_key]).toStrictEqual(token);
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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