Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Provide digestFetch function
- */
- const crypto = require('crypto');
- const nodeFetch = require('node-fetch');
- const mergeOptions = require('merge-options');
- const cnonceSize = 32;
- const nonceRaw = 'abcdef0123456789';
- function makeNonce () {
- let uid = '';
- for (let i = 0; i < cnonceSize; ++i) {
- uid += nonceRaw[Math.floor(Math.random() * nonceRaw.length)];
- }
- return uid;
- }
- function md5(data) {
- return crypto.createHash('md5').update(data).digest('hex');
- }
- function ha1Compute(algorithm, user, realm, pass, nonce, cnonce) {
- const ha1 = md5(`${user}:${realm}:${pass}`);
- if (algorithm && algorithm.toLowerCase() === 'md5-sess') {
- return md5(`${ha1}:${nonce}:${cnonce}`);
- } else {
- return ha1;
- }
- }
- function digestFetch(username, password) {
- const digest = { nc: 0, algorithm: 'md5' };
- let hasAuth = false;
- function parseAuth (response) {
- const authHeader = response.headers.get('www-authenticate');
- if (authHeader.split(/\s/)[0].toLowerCase() !== 'digest') {
- return false;
- }
- const re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi;
- for (;;) {
- var match = re.exec(authHeader);
- if (!match) {
- break;
- }
- digest[match[1]] = match[2] || match[3];
- }
- digest.nc++;
- digest.cnonce = makeNonce();
- return true;
- }
- function addAuth (url, options) {
- if (!hasAuth) {
- return options;
- }
- const _url = url.replace('//', '');
- const uri = _url.indexOf('/') == -1 ? '/' : _url.slice(_url.indexOf('/'));
- const method = options.method ? options.method.toUpperCase() : 'GET';
- const qop = /(^|,)\s*auth\s*($|,)/.test(digest.qop) && 'auth';
- const ncString = (`00000000${digest.nc}`).slice(-8);
- const cnonce = digest.cnonce;
- const ha1 = ha1Compute(digest.algorithm, username, digest.realm, password, digest.nonce, digest.cnonce);
- const ha2 = md5(`${method}:${uri}`);
- const digestResponse = qop
- ? md5(`${ha1}:${digest.nonce}:${ncString}:${digest.cnonce}:${qop}:${ha2}`)
- : md5(`${ha1}:${digest.nonce}:${ha2}`);
- const authValues = {
- username,
- realm: digest.realm,
- nonce: digest.nonce,
- uri,
- qop,
- response: digestResponse,
- nc: ncString,
- cnonce: digest.cnonce,
- algorithm: digest.algorithm,
- opaque: digest.opaque
- };
- const authHeader = [];
- for (var k in authValues) {
- if (authValues[k]) {
- if (k === 'qop' || k === 'nc' || k === 'algorithm') {
- authHeader.push(`${k}=${authValues[k]}`);
- } else {
- authHeader.push(`${k}="${authValues[k]}"`);
- }
- }
- }
- return mergeOptions(options, { headers: { Authorization: 'Digest ' + authHeader.join(', ') } });
- }
- return async function fetch (url, options = {}) {
- const response = await nodeFetch(url, addAuth(url, options));
- if (response.status == 401) {
- hasAuth = parseAuth(response);
- if (hasAuth) {
- const response2 = await nodeFetch(url, addAuth(url, options));
- if (response2.status == 401) {
- hasAuth = false;
- } else {
- digest.nc++;
- }
- return response2;
- }
- } else {
- digest.nc++;
- }
- return response;
- }
- }
- module.exports = digestFetch;
Add Comment
Please, Sign In to add comment