adal-node
Advanced tools
Comparing version 0.1.5 to 0.1.6
@@ -62,2 +62,6 @@ /* | ||
// Constants | ||
var METADATA_CLIENTID = '_clientId'; | ||
var METADATA_AUTHORITY = '_authority'; | ||
function nop(placeHolder, callback) { | ||
@@ -137,3 +141,5 @@ callback(); | ||
CacheDriver.prototype._find = function(query, callback) { | ||
var authorityQuery = { _authority : this._authority }; | ||
var authorityQuery = {}; | ||
authorityQuery[METADATA_AUTHORITY] = this._authority; | ||
_.extend(query, authorityQuery); | ||
@@ -153,3 +159,3 @@ this._cache.find(query, callback); | ||
if (query.clientId) { | ||
potentialEntriesQuery._clientId = query.clientId; | ||
potentialEntriesQuery[METADATA_CLIENTID] = query.clientId; | ||
} | ||
@@ -235,3 +241,19 @@ if (query.userId) { | ||
CacheDriver.prototype._replaceEntry = function(entryToReplace, tokenResponse, callback) { | ||
/** | ||
* The response from a token refresh request never contains an id_token and therefore no | ||
* userInfo can be created from the response. This function creates a new cache entry | ||
* combining the id_token based info and cache metadata from the cache entry that was refreshed with the | ||
* new tokens in the refresh response. | ||
* @param {object} entry A cache entry corresponding to the resfreshResponse. | ||
* @param {object} refreshResponse The response from a token refresh request for the entry parameter. | ||
* @return {object} A new cache entry. | ||
*/ | ||
CacheDriver.prototype._createEntryFromRefresh = function(entry, refreshResponse) { | ||
var newEntry = _.clone(entry); | ||
newEntry = _.extend(newEntry, refreshResponse); | ||
this._log.verbose('Created new cache entry from refresh response.'); | ||
return newEntry; | ||
}; | ||
CacheDriver.prototype._replaceEntry = function(entryToReplace, newEntry, callback) { | ||
var self = this; | ||
@@ -243,3 +265,3 @@ this.remove(entryToReplace, function(err) { | ||
} | ||
self.add(tokenResponse, callback); | ||
self.add(newEntry, callback); | ||
}); | ||
@@ -261,3 +283,4 @@ }; | ||
self._replaceEntry(entry, tokenResponse, function(err) { | ||
var newEntry = self._createEntryFromRefresh(entry, tokenResponse); | ||
self._replaceEntry(entry, newEntry, function(err) { | ||
if (err) { | ||
@@ -268,3 +291,3 @@ self._log.error('error refreshing expired token', err); | ||
} | ||
callback(err, tokenResponse); | ||
callback(err, newEntry); | ||
}); | ||
@@ -287,3 +310,4 @@ }); | ||
self.add(tokenResponse, function(err) { | ||
var newEntry = self._createEntryFromRefresh(entry, tokenResponse); | ||
self.add(newEntry, function(err) { | ||
if (err) { | ||
@@ -294,3 +318,3 @@ self._log.error('error refreshing mrrt', err); | ||
} | ||
callback(err, tokenResponse); | ||
callback(err, newEntry); | ||
}); | ||
@@ -310,5 +334,7 @@ }); | ||
var expiryDate = entry[TokenResponseFields.EXPIRES_ON]; | ||
var now = new Date(); | ||
if (isResourceSpecific && now.isAfter(expiryDate)) { | ||
// Add some buffer in to the time comparison to account for clock skew or latency. | ||
var nowPlusBuffer = (new Date()).addMinutes(constants.Misc.CLOCK_BUFFER); | ||
if (isResourceSpecific && nowPlusBuffer.isAfter(expiryDate)) { | ||
this._log.info('Cached token is expired. Refreshing: ' + expiryDate); | ||
@@ -402,3 +428,3 @@ this._refreshExpiredEntry(entry, callback); | ||
function isMRRT(entry) { | ||
return entry.resource; | ||
return entry.resource ? true : false; | ||
} | ||
@@ -450,2 +476,30 @@ | ||
/** | ||
* Checks to see if the entry has cache metadata already. If it does | ||
* then it probably came from a refresh operation and the metadata | ||
* was copied from the originating entry. | ||
* @param {object} entry The entry to check | ||
* @return {bool} Returns true if the entry has already been augmented | ||
* with cache metadata. | ||
*/ | ||
CacheDriver.prototype._entryHasMetadata = function(entry) { | ||
return (_.has(entry, METADATA_CLIENTID) && _.has(entry, METADATA_AUTHORITY)); | ||
}; | ||
CacheDriver.prototype._augmentEntryWithCacheMetadata = function(entry) { | ||
if (this._entryHasMetadata(entry)) { | ||
return; | ||
} | ||
if (isMRRT(entry)) { | ||
this._log.verbose('Added entry is MRRT'); | ||
entry.isMRRT = true; | ||
} else { | ||
entry.resource = this._resource; | ||
} | ||
entry[METADATA_CLIENTID] = this._clientId; | ||
entry[METADATA_AUTHORITY] = this._authority; | ||
}; | ||
/** | ||
* Adds a single entry to the cache. | ||
@@ -455,3 +509,3 @@ * @param {object} entry The entry to add. | ||
* @param {string} resource The id of the resource for which the cached token was obtained. | ||
* @param {Function} callback Called back on completion. The first parameter may contain an error. | ||
* @param {Function} callback Called back on completion. The first parameter may contain an error. | ||
*/ | ||
@@ -462,2 +516,4 @@ CacheDriver.prototype.add = function(entry, callback) { | ||
this._augmentEntryWithCacheMetadata(entry); | ||
this._updateRefreshTokens(entry, function(err) { | ||
@@ -469,12 +525,2 @@ if (err) { | ||
if (isMRRT(entry)) { | ||
self._log.verbose('Added entry is MRRT'); | ||
entry.isMRRT = true; | ||
} else { | ||
entry.resource = self._resource; | ||
} | ||
entry._clientId = self._clientId; | ||
entry._authority = self._authority; | ||
self._cache.add([entry], function(err) { | ||
@@ -481,0 +527,0 @@ callback(err); |
@@ -98,3 +98,4 @@ /* | ||
Misc : { | ||
MAX_DATE : 0xffffffff | ||
MAX_DATE : 0xffffffff, | ||
CLOCK_BUFFER : 5 // In minutes. | ||
}, | ||
@@ -101,0 +102,0 @@ |
@@ -440,10 +440,14 @@ /* | ||
TokenRequest.prototype.getTokenFromCacheWithRefresh = function(userId, callback) { | ||
var self = this; | ||
this._log.info('Getting token from cache with refresh if necessary.'); | ||
this._userId = userId; | ||
// This call should never try to fetch a new token, so pass a dummy token | ||
// fetching function. | ||
this._getToken(callback, function(innerCallback){ innerCallback(); }); | ||
this._getToken(callback, function(innerCallback){ | ||
// If this method was called then no cached entry was found. Since | ||
// this particular version of acquireToken can only retrieve tokens | ||
// from the cache, return an error. | ||
innerCallback(self._log.createError('Entry not found in cache.')); | ||
}); | ||
}; | ||
module.exports = TokenRequest; |
@@ -18,3 +18,3 @@ { | ||
}, | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "Windows Azure Active Directory Client Library for node", | ||
@@ -21,0 +21,0 @@ "keywords": [ "node", "azure", "AAD", "adal", "adfs", "oauth" ], |
@@ -58,3 +58,3 @@ /* | ||
/* | ||
* Compares to lists of cache entries. The lists will be sorted before comparison and the comparison will | ||
* Compares two lists of cache entries. The lists will be sorted before comparison and the comparison will | ||
* take in to account the different ways that MRRT is indicated when a cache entry is submitted to the cache | ||
@@ -405,2 +405,3 @@ * and once it is in the cache. | ||
responses.push(refreshedResponse.cachedResponse); | ||
var cacheDriver = new CacheDriver(fakeTokenRequest._callContext, authority, unknownResource, cp.clientId, memCache, refreshFunction); | ||
@@ -412,5 +413,22 @@ cacheDriver.find(null, function(err, entry) { | ||
assert(refreshedRefreshToken === entry['refreshToken'], 'Returned refresh token did not match expected'); | ||
compareInputAndCache(responses, memCache, numMRRTTokens + 1, entry.refreshToken); | ||
// Now ensure that the refreshed token can be successfully found in the cache. | ||
var query = { | ||
userId : entry.userId, | ||
clientId : cp.clientId | ||
}; | ||
cacheDriver.find(query, function(err, recentlyCachedEntry) { | ||
if (!err) { | ||
assert(recentlyCachedEntry, 'Expected a returned entry but none was returned.'); | ||
assertEntriesEqual(entry, recentlyCachedEntry, 'Token returned from cache was not the same as the one that was recently cached.'); | ||
compareInputAndCache(responses, memCache, numMRRTTokens + 1, entry.refreshToken); | ||
} | ||
done(err); | ||
return; | ||
}); | ||
} else { | ||
done(err); | ||
return; | ||
} | ||
done(err); | ||
return; | ||
}); | ||
@@ -482,4 +500,3 @@ } else { | ||
responses = removeResponse(responses, expiredEntry); | ||
responses.push(refreshedResponse.decodedResponse); | ||
responses.push(refreshedResponse.cachedResponse); | ||
var cacheDriver = new CacheDriver(fakeTokenRequest._callContext, authority, expiredEntry.resource, cp.clientId, memCache, refreshFunction); | ||
@@ -492,5 +509,21 @@ cacheDriver.find(null, function(err, entry) { | ||
compareInputAndCache(responses, memCache, numMRRTTokens, finalMrrt); | ||
// Now ensure that the refreshed token can be successfully found in the cache. | ||
var query = { | ||
userId : entry.userId, | ||
clientId : cp.clientId | ||
}; | ||
cacheDriver.find(query, function(err, recentlyCachedEntry) { | ||
if (!err) { | ||
assert(recentlyCachedEntry, 'Expected a returned entry but none was returned.'); | ||
assertEntriesEqual(entry, recentlyCachedEntry, 'Token returned from cache was not the same as the one that was recently cached.'); | ||
compareInputAndCache(responses, memCache, numMRRTTokens, finalMrrt); | ||
} | ||
done(err); | ||
return; | ||
}); | ||
} else { | ||
done(err); | ||
return; | ||
} | ||
done(err); | ||
return; | ||
}); | ||
@@ -497,0 +530,0 @@ } else { |
@@ -161,3 +161,12 @@ /* | ||
}); | ||
test('no-cached-token-found-error', function(done) { | ||
var context = new AuthenticationContext(cp.authUrl); | ||
context.acquireToken(cp.resource, 'unknownUser', cp.clientId, function(err) { | ||
assert(err, 'Expected an error and non was recieved.'); | ||
assert(-1 !== err.message.indexOf('not found'), 'Returned error did not contain expected message: ' + err.message); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
1023569
6818
3