Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Commit 22c2715

Browse files
committed
Merge branch 'dev' into fix_issue
2 parents e204d87 + 00daeb8 commit 22c2715

21 files changed

+263
-157
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ var AuthenticationContext = require('adal-node').AuthenticationContext;
2929

3030
var clientId = 'yourClientIdHere';
3131
var clientSecret = 'yourAADIssuedClientSecretHere'
32-
var redirectUri = 'yourRedirectUriHere';
3332
var authorityHostUrl = 'https://login.windows.net';
3433
var tenant = 'myTenant';
3534
var authorityUrl = authorityHostUrl + '/' + tenant;
@@ -40,8 +39,8 @@ var templateAuthzUrl = 'https://login.windows.net/' +
4039
'/oauth2/authorize?response_type=code&client_id=' +
4140
clientId +
4241
'&redirect_uri=' +
43-
redirectUri + '
44-
&state=<state>&resource=' +
42+
redirectUri +
43+
'&state=<state>&resource=' +
4544
resource;
4645

4746
function createAuthorizationUrl(state) {

changelog.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
Version 0.1.18
2+
--------------
3+
Release Date: 5 Feb 2016
4+
* Add oid in IDTokenMap to expose for returned user info.
5+
6+
Version 0.1.17
7+
--------------
8+
Release Date: 8 Oct 2015
9+
* Add support for cross tenant refresh token
10+
111
Version 0.1.16
212
--------------
313
Release Date: 3 Sep 2015

lib/authentication-context.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,9 @@ AuthenticationContext.prototype.acquireUserCode = function(resource, clientId, l
400400
};
401401

402402
/**
403-
* Gets a new access token using via a device code.
403+
* Gets a new access token using via a device code.
404+
* @note This method doesn't look up the cache, it only stores the returned token into cache. To look up cache before making a new request,
405+
* please use acquireToken.
404406
* @param {string} clientId The OAuth client id of the calling application.
405407
* @param {object} userCodeInfo Contains device_code, retry interval, and expire time for the request for get the token.
406408
* @param {AcquireTokenCallback} callback The callback function.
@@ -418,7 +420,7 @@ AuthenticationContext.prototype.acquireTokenWithDeviceCode = function(resource,
418420
var self = this;
419421
this._acquireToken(callback, function() {
420422
var tokenRequest = new TokenRequest(this._callContext, this, clientId, resource, null);
421-
self._tokenRequestWithUserCode[userCodeInfo[constants.OAuth2.DeviceCodeResponseParameters.DEVICE_CODE]] = tokenRequest;
423+
self._tokenRequestWithUserCode[userCodeInfo[constants.UserCodeResponseFields.DEVICE_CODE]] = tokenRequest;
422424
tokenRequest.getTokenWithDeviceCode(userCodeInfo, callback);
423425
})
424426
};
@@ -438,15 +440,15 @@ AuthenticationContext.prototype.cancelRequestToGetTokenWithDeviceCode = function
438440
return;
439441
}
440442

441-
if (!this._tokenRequestWithUserCode || !this._tokenRequestWithUserCode[userCodeInfo[constants.OAuth2.DeviceCodeResponseParameters.DEVICE_CODE]]) {
443+
if (!this._tokenRequestWithUserCode || !this._tokenRequestWithUserCode[userCodeInfo[constants.UserCodeResponseFields.DEVICE_CODE]]) {
442444
callback(new Error('No acquireTokenWithDeviceCodeRequest existed to be cancelled'));
443445
return;
444446
}
445447

446-
var tokenRequestToBeCancelled = this._tokenRequestWithUserCode[userCodeInfo[constants.OAuth2.DeviceCodeResponseParameters.DEVICE_CODE]];
448+
var tokenRequestToBeCancelled = this._tokenRequestWithUserCode[userCodeInfo[constants.UserCodeResponseFields.DEVICE_CODE]];
447449
tokenRequestToBeCancelled.cancelTokenRequestWithDeviceCode();
448450

449-
delete this._tokenRequestWithUserCode[constants.OAuth2.DeviceCodeResponseParameters.DEVICE_CODE];
451+
delete this._tokenRequestWithUserCode[constants.UserCodeResponseFields.DEVICE_CODE];
450452
};
451453

452454
var exports = {

lib/cache-driver.js

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ function CacheDriver(callContext, authority, resource, clientId, cache, refreshF
137137
* @param {QueryCallback} callback
138138
*/
139139
CacheDriver.prototype._find = function(query, callback) {
140-
var authorityQuery = {};
141-
authorityQuery[METADATA_AUTHORITY] = this._authority;
142-
143-
_.extend(query, authorityQuery);
144140
this._cache.find(query, callback);
145141
};
146142

@@ -171,10 +167,11 @@ CacheDriver.prototype._getPotentialEntries = function(query, callback) {
171167

172168
/**
173169
* Finds all multi resource refresh tokens in the cache.
170+
* Refresh token is bound to userId, clientId.
174171
* @param {QueryCallback} callback
175172
*/
176173
CacheDriver.prototype._findMRRTTokensForUser = function(user, callback) {
177-
this._find({ isMRRT : true, userId : user }, callback);
174+
this._find({ isMRRT : true, userId : user, _clientId : this._clientId}, callback);
178175
};
179176

180177
/**
@@ -201,13 +198,12 @@ CacheDriver.prototype._loadSingleEntryFromCache = function(query, callback) {
201198
}
202199

203200
var returnVal;
204-
var isResourceSpecific;
201+
var isResourceTenantSpecific;
205202

206203
if (potentialEntries && 0 < potentialEntries.length) {
207-
var resourceSpecificEntries;
208-
resourceSpecificEntries = _.where(potentialEntries, { resource : self._resource });
204+
var resourceTenantSpecificEntries = _.where(potentialEntries, { resource : self._resource, _authority : self._authority });
209205

210-
if (!resourceSpecificEntries || 0 === resourceSpecificEntries.length) {
206+
if (!resourceTenantSpecificEntries || 0 === resourceTenantSpecificEntries.length) {
211207
self._log.verbose('No resource specific cache entries found.');
212208

213209
// There are no resource specific entries. Find an MRRT token.
@@ -219,10 +215,10 @@ CacheDriver.prototype._loadSingleEntryFromCache = function(query, callback) {
219215
self._log.verbose('No MRRT tokens found.');
220216
}
221217

222-
} else if (resourceSpecificEntries.length === 1) {
218+
} else if (resourceTenantSpecificEntries.length === 1) {
223219
self._log.verbose('Resource specific token found.');
224-
returnVal = resourceSpecificEntries[0];
225-
isResourceSpecific = true;
220+
returnVal = resourceTenantSpecificEntries[0];
221+
isResourceTenantSpecific = true;
226222
}else {
227223
callback(self._log.createError('More than one token matches the criteria. The result is ambiguous.'));
228224
return;
@@ -231,7 +227,7 @@ CacheDriver.prototype._loadSingleEntryFromCache = function(query, callback) {
231227
if (returnVal) {
232228
self._log.verbose('Returning token from cache lookup, ' + createTokenIdMessage(returnVal));
233229
}
234-
callback(null, returnVal, isResourceSpecific);
230+
callback(null, returnVal, isResourceTenantSpecific);
235231
});
236232
};
237233

@@ -247,6 +243,11 @@ CacheDriver.prototype._loadSingleEntryFromCache = function(query, callback) {
247243
CacheDriver.prototype._createEntryFromRefresh = function(entry, refreshResponse) {
248244
var newEntry = _.clone(entry);
249245
newEntry = _.extend(newEntry, refreshResponse);
246+
247+
if (entry.isMRRT && this._authority !== entry[METADATA_AUTHORITY]) {
248+
newEntry[METADATA_AUTHORITY] = this._authority;
249+
}
250+
250251
this._log.verbose('Created new cache entry from refresh response.');
251252
return newEntry;
252253
};
@@ -348,7 +349,7 @@ CacheDriver.prototype.find = function(query, callback) {
348349
var self = this;
349350
query = query || {};
350351
this._log.verbose('finding with query:' + JSON.stringify(query));
351-
this._loadSingleEntryFromCache(query, function(err, entry, isResourceSpecific) {
352+
this._loadSingleEntryFromCache(query, function(err, entry, isResourceTenantSpecific) {
352353
if (err) {
353354
callback(err);
354355
return;
@@ -359,7 +360,7 @@ CacheDriver.prototype.find = function(query, callback) {
359360
return;
360361
}
361362

362-
self._refreshEntryIfNecessary(entry, isResourceSpecific, function(err, newEntry) {
363+
self._refreshEntryIfNecessary(entry, isResourceTenantSpecific, function(err, newEntry) {
363364
callback(err, newEntry);
364365
return;
365366
});

lib/constants.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ var Constants = {
8585
'tid' : 'tenantId',
8686
'given_name' : 'givenName',
8787
'family_name' : 'familyName',
88-
'idp' : 'identityProvider'
88+
'idp' : 'identityProvider',
89+
'oid': 'oid'
8990
}
9091
},
9192

@@ -103,14 +104,14 @@ var Constants = {
103104
},
104105

105106
UserCodeResponseFields : {
106-
USER_CODE : 'user_code',
107-
DEVICE_CODE: 'device_code',
108-
VERIFICATION_URL: 'verification_url',
109-
EXPIRES_IN: 'expires_in',
107+
USER_CODE : 'userCode',
108+
DEVICE_CODE: 'deviceCode',
109+
VERIFICATION_URL: 'verificationUrl',
110+
EXPIRES_IN: 'expiresIn',
110111
INTERVAL: 'interval',
111112
MESSAGE: 'message',
112113
ERROR: 'error',
113-
ERROR_DESCRIPTION: 'error_description'
114+
ERROR_DESCRIPTION: 'errorDescription'
114115
},
115116

116117
IdTokenFields : {

lib/oauth2client.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,21 @@ OAuth2Client.prototype._createTokenUrl = function () {
8787
var tokenUrl = url.parse(this._tokenEndpoint);
8888

8989
var parameters = {};
90-
parameters.slice = 'testslice';
9190
parameters[OAuth2Parameters.AAD_API_VERSION] = '1.0';
9291

9392
tokenUrl.search = querystring.stringify(parameters);
94-
9593
return tokenUrl;
9694
};
9795

96+
/**
97+
* Constructs the user code info request url.
98+
* @private
99+
* @return {URL}
100+
*/
98101
OAuth2Client.prototype._createDeviceCodeUrl = function () {
99102
var deviceCodeUrl = url.parse(this._deviceCodeEndpoint);
100103

101104
var parameters = {};
102-
parameters.slice = 'testslice';
103105
parameters[OAuth2Parameters.AAD_API_VERSION] = '1.0';
104106

105107
deviceCodeUrl.search = querystring.stringify(parameters);
@@ -125,8 +127,8 @@ OAuth2Client.prototype._parseOptionalInts = function (obj, keys) {
125127
};
126128

127129
/**
128-
* Cracks a JWS encoded JWT into it's three parts.
129-
* @param {string} jwtToken The token to crack.
130+
* Parses a JWS encoded JWT into it's three parts.
131+
* @param {string} jwtToken The token to parse.
130132
* @return {object} The three JWS parts, header, JWSPayload, and JWSSig, or undefined.
131133
*/
132134
OAuth2Client.prototype._crackJwt = function(jwtToken) {
@@ -433,7 +435,7 @@ OAuth2Client.prototype._createPostOption = function (postUrl, urlEncodedRequestF
433435
var postOptions = util.createRequestOptions(
434436
this,
435437
{
436-
'url' : postUrl,
438+
'url' : url.format(postUrl),
437439
body : urlEncodedRequestForm,
438440
headers: {
439441
'Content-Type': 'application/x-www-form-urlencoded'

lib/token-request.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var OAuth2Scope = constants.OAuth2.Scope;
3636
var Saml = constants.Saml;
3737
var AccountType = constants.UserRealm.AccountType;
3838
var WSTrustVersion = constants.WSTrustVersion;
39-
var DeviceCodeResponseParameters = constants.OAuth2.DeviceCodeResponseParameters;
39+
var DeviceCodeResponseParameters = constants.UserCodeResponseFields;
4040

4141
/**
4242
* Constructs a new TokenRequest object.
@@ -163,6 +163,18 @@ TokenRequest.prototype._getTokenWithCacheWrapper = function(callback, getTokenFu
163163
});
164164
};
165165

166+
/**
167+
* Store token into cache.
168+
* @param {object} tokenResponse Token response to be added into the cache.
169+
*/
170+
TokenRequest.prototype._addTokenIntoCache = function(tokenResponse, callback) {
171+
this._cacheDriver = this._createCacheDriver();
172+
this._log.verbose('Storing retrieved token into cache');
173+
this._cacheDriver.add(tokenResponse, function(err) {
174+
callback(err, tokenResponse);
175+
});
176+
};
177+
166178
/**
167179
* Adds an OAuth parameter to the paramters object if the parameter is
168180
* not null or undefined.
@@ -555,9 +567,10 @@ TokenRequest.prototype.getTokenWithCertificate = function(certificate, thumbprin
555567

556568
TokenRequest.prototype.getTokenWithDeviceCode = function(userCodeInfo, callback) {
557569
this._log.info('Getting a token via device code');
570+
var self = this;
558571

559572
var oauthParameters = this._createOAuthParameters(OAuth2GrantType.DEVICE_CODE);
560-
oauthParameters[OAuth2Parameters.CODE] = userCodeInfo[OAuth2Parameters.DEVICE_CODE];
573+
oauthParameters[OAuth2Parameters.CODE] = userCodeInfo[DeviceCodeResponseParameters.DEVICE_CODE];
561574

562575
var interval = userCodeInfo[DeviceCodeResponseParameters.INTERVAL];
563576
var expires_in = userCodeInfo[DeviceCodeResponseParameters.EXPIRES_IN];
@@ -566,8 +579,14 @@ TokenRequest.prototype.getTokenWithDeviceCode = function(userCodeInfo, callback)
566579
callback(new Error('invalid refresh interval'));
567580
}
568581

569-
this._getTokenWithCacheWrapper(callback, function(getTokenCompleteCallback) {
570-
this._oauthGetTokenByPolling(oauthParameters, interval, expires_in, getTokenCompleteCallback);
582+
this._oauthGetTokenByPolling(oauthParameters, interval, expires_in, function(err, tokenResponse) {
583+
if (err) {
584+
self._log.verbose('Token polling request returend with err.');
585+
callback(err, tokenResponse);
586+
}
587+
else {
588+
self._addTokenIntoCache(tokenResponse, callback);
589+
}
571590
});
572591
};
573592

lib/util.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ var ADAL_VERSION;
3434
*/
3535

3636
function loadAdalVersion() {
37-
var packagePath = __dirname + '/../package.json';
38-
var packageJson = JSON.parse(fs.readFileSync(packagePath));
37+
var packageData = fs.readFileSync(__dirname + '/../package.json');
38+
var packageJson = JSON.parse(packageData);
3939
ADAL_VERSION = packageJson.version;
4040
}
4141

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@
1515
"type": "git",
1616
"url": "https://github.com/AzureAD/azure-activedirectory-library-for-nodejs.git"
1717
},
18-
"version": "0.1.16",
18+
"version": "0.1.18",
1919
"description": "Windows Azure Active Directory Client Library for node",
2020
"keywords": [ "node", "azure", "AAD", "adal", "adfs", "oauth" ],
2121
"main": "./lib/adal.js",
2222
"engines": { "node": ">= 0.6.15" },
2323
"dependencies": {
2424
"date-utils": "*",
2525
"jws": "3.x.x",
26-
"node-uuid": "1.4.1",
27-
"request": ">= 2.9.203",
26+
"node-uuid": "1.4.7",
27+
"request": ">= 2.52.0",
2828
"underscore": ">= 1.3.1",
2929
"xmldom": ">= 0.1.x",
3030
"xpath.js": "~1.0.5",

sample/device-code-sample.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var fs = require('fs');
2424
var adal = require('../lib/adal.js');
2525
var async = require('async');
2626
var url = require('url');
27+
var MemoryCache = require('../lib/memory-cache');
2728

2829
var AuthenticationContext = adal.AuthenticationContext;
2930

@@ -67,20 +68,23 @@ if (parametersFile) {
6768

6869
if (!parametersFile) {
6970
sampleParameters = {
70-
tenant : '',
71-
authorityHostUrl : '',
72-
clientId : ''
71+
tenant : 'convergeTest.onmicrosoft.com',
72+
authorityHostUrl : 'https://login.microsoftonline.com',
73+
clientId : '',
74+
anothertenant: ''
7375
};
7476
}
7577

7678
var authorityUrl = sampleParameters.authorityHostUrl + '/' + sampleParameters.tenant;
7779

7880
var resource = '00000002-0000-0000-c000-000000000000';
81+
var userId = '';
7982

8083
//turnOnLogging();
8184

82-
var context = new AuthenticationContext(authorityUrl);
85+
var cache = new MemoryCache();
8386

87+
var context = new AuthenticationContext(authorityUrl, null, cache);
8488
context.acquireUserCode(resource, sampleParameters.clientId, 'es-mx', function (err, response) {
8589
if (err) {
8690
console.log('well that didn\'t work: ' + err.stack);
@@ -93,8 +97,20 @@ context.acquireUserCode(resource, sampleParameters.clientId, 'es-mx', function (
9397
console.log(err);
9498
}
9599
else {
96-
console.log(tokenResponse);
100+
authorityUrl = sampleParameters.authorityHostUrl + '/' + sampleParameters.anothertenant;
101+
102+
var context2 = new AuthenticationContext(authorityUrl, null, cache);
103+
context2.acquireToken(resource, userId, sampleParameters.clientId, function (err, tokenResponse) {
104+
if (err) {
105+
console.log('error happens when acquiring token with device code');
106+
console.log(err);
107+
}
108+
else {
109+
console.log(tokenResponse);
110+
}
111+
});
97112
}
98113
});
99114
}
100115
});
116+

sample/website-sample.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ app.get('/login', function(req, res) {
9090

9191
res.send('\
9292
<head>\
93-
<title>FooBar</title>\
93+
<title>test</title>\
9494
</head>\
9595
<body>\
9696
<a href="./auth">Login</a>\

0 commit comments

Comments
 (0)