adal-node
Advanced tools
Comparing version 0.1.10 to 0.1.11
@@ -0,1 +1,7 @@ | ||
Version 0.1.11 | ||
-------------- | ||
Release Date: 16 December 2014 | ||
* Added support for certificate authentication for confidential clients. | ||
Version 0.1.10 | ||
@@ -2,0 +8,0 @@ -------------- |
@@ -338,4 +338,27 @@ /* | ||
util.adalInit(); | ||
/** | ||
* Gets a new access token using via a certificate credential. | ||
* @param {string} resource A URI that identifies the resource for which the token is valid. | ||
* @param {string} clientId The OAuth client id of the calling application. | ||
* @param {string} certificate A PEM encoded certificate private key. | ||
* @param {string} thumbprint A hex encoded thumbprint of the certificate. | ||
* @param {AcquireTokenCallback} callback The callback function. | ||
*/ | ||
AuthenticationContext.prototype.acquireTokenWithClientCertificate = function(resource, clientId, certificate, thumbprint, callback) { | ||
argument.validateCallbackType(callback); | ||
try { | ||
argument.validateStringParameter(resource, 'resource'); | ||
argument.validateStringParameter(certificate, 'certificate'); | ||
argument.validateStringParameter(thumbprint, 'thumbprint'); | ||
} catch(err) { | ||
callback(err); | ||
return; | ||
} | ||
this._acquireToken(callback, function() { | ||
var tokenRequest = new TokenRequest(this._callContext, this, clientId, resource); | ||
tokenRequest.getTokenWithCertificate(certificate, thumbprint, callback); | ||
}); | ||
}; | ||
var exports = { | ||
@@ -351,2 +374,3 @@ AuthenticationContext : AuthenticationContext, | ||
module.exports = exports; | ||
util.adalInit(); | ||
module.exports = exports; |
@@ -1,2 +0,2 @@ | ||
/* | ||
/* | ||
* @copyright | ||
@@ -3,0 +3,0 @@ * Copyright © Microsoft Open Technologies, Inc. |
@@ -27,2 +27,4 @@ /* | ||
GRANT_TYPE : 'grant_type', | ||
CLIENT_ASSERTION : 'client_assertion', | ||
CLIENT_ASSERTION_TYPE : 'client_assertion_type', | ||
CLIENT_ID : 'client_id', | ||
@@ -45,2 +47,3 @@ CLIENT_SECRET : 'client_secret', | ||
CLIENT_CREDENTIALS : 'client_credentials', | ||
JWT_BEARER : 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer', | ||
PASSWORD : 'password', | ||
@@ -104,2 +107,12 @@ SAML1 : 'urn:ietf:params:oauth:grant-type:saml1_1-bearer', | ||
Jwt : { | ||
SELF_SIGNED_JWT_LIFETIME : 10, // 10 mins in mins | ||
AUDIENCE : 'aud', | ||
ISSUER : 'iss', | ||
SUBJECT : 'sub', | ||
NOT_BEFORE : 'nbf', | ||
EXPIRES_ON : 'exp', | ||
JWT_ID : 'jti' | ||
}, | ||
AADConstants : { | ||
@@ -162,2 +175,2 @@ WORLD_WIDE_AUTHORITY : 'login.windows.net', | ||
module.exports = Constants; | ||
module.exports = Constants; |
@@ -28,2 +28,3 @@ /* | ||
var OAuth2Client = require('./oauth2client'); | ||
var SelfSignedJwt = require('./self-signed-jwt'); | ||
var UserRealm = require('./user-realm'); | ||
@@ -80,2 +81,6 @@ var WSTrustRequest = require('./wstrust-request'); | ||
TokenRequest.prototype._createSelfSignedJwt = function() { | ||
return new SelfSignedJwt(this._callContext, this._authenticationContext._authority, this._clientId); | ||
}; | ||
TokenRequest.prototype._oauthGetToken = function(oauthParameters, callback) { | ||
@@ -117,3 +122,3 @@ var client = this._createOAuth2Client(); | ||
} else { | ||
this._log.verbose('No userId passed.'); | ||
this._log.verbose('No userId passed for cache query.'); | ||
} | ||
@@ -124,3 +129,4 @@ | ||
TokenRequest.prototype._getToken = function(callback, getTokenFunc) { | ||
TokenRequest.prototype._getTokenWithCacheWrapper = function(callback, getTokenFunc) { | ||
var self = this; | ||
@@ -360,3 +366,3 @@ this._cacheDriver = this._createCacheDriver(); | ||
this._userId = username; | ||
this._getToken(callback, function(innerCallback) { | ||
this._getTokenWithCacheWrapper(callback, function(getTokenCompleteCallback) { | ||
var self = this; | ||
@@ -366,3 +372,3 @@ this._userRealm = this._createUserRealmRequest(username); | ||
if (err) { | ||
innerCallback(err); | ||
getTokenCompleteCallback(err); | ||
return; | ||
@@ -373,9 +379,9 @@ } | ||
case AccountType.Managed: | ||
self._getTokenUsernamePasswordManaged(username, password, innerCallback); | ||
self._getTokenUsernamePasswordManaged(username, password, getTokenCompleteCallback); | ||
return; | ||
case AccountType.Federated: | ||
self._getTokenUsernamePasswordFederated(username, password, innerCallback); | ||
self._getTokenUsernamePasswordFederated(username, password, getTokenCompleteCallback); | ||
return; | ||
default: | ||
innerCallback(self._log.createError('Server returned an unknown AccountType: ' + self._userRealm.AccountType)); | ||
getTokenCompleteCallback(self._log.createError('Server returned an unknown AccountType: ' + self._userRealm.AccountType)); | ||
} | ||
@@ -395,3 +401,3 @@ }); | ||
this._getToken(callback, function(innerCallback) { | ||
this._getTokenWithCacheWrapper(callback, function(getTokenCompleteCallback) { | ||
var oauthParameters = this._createOAuthParameters(OAuth2GrantType.CLIENT_CREDENTIALS); | ||
@@ -401,3 +407,3 @@ | ||
this._oauthGetToken(oauthParameters, innerCallback); | ||
this._oauthGetToken(oauthParameters, getTokenCompleteCallback); | ||
}); | ||
@@ -467,10 +473,58 @@ }; | ||
this._userId = userId; | ||
this._getToken(callback, function(innerCallback){ | ||
this._getTokenWithCacheWrapper(callback, function(getTokenCompleteCallback) { | ||
// 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.')); | ||
getTokenCompleteCallback(self._log.createError('Entry not found in cache.')); | ||
}); | ||
}; | ||
/** | ||
* Creates a self signed jwt. | ||
* @param {string} authorityUrl | ||
* @param {string} certificate A PEM encoded certificate private key. | ||
* @param {string} thumbprint | ||
* @return {string} A self signed JWT | ||
*/ | ||
TokenRequest.prototype._createJwt = function(authorityUrl, certificate, thumbprint) { | ||
var jwt; | ||
var ssj = this._createSelfSignedJwt(); | ||
jwt = ssj.create(certificate, thumbprint); | ||
if (!jwt) { | ||
throw this._log.createError('Failed to create JWT'); | ||
} | ||
return jwt; | ||
}; | ||
/** | ||
* Obtains a token via a certificate. The certificate is used to generate a self signed | ||
* JWT token that is passed as a client_assertion. | ||
* @param {string} certificate A PEM encoded certificate private key. | ||
* @param {string} thumbprint A hex encoded thumbprint of the certificate. | ||
* @param {AcquireTokenCallback} callback | ||
*/ | ||
TokenRequest.prototype.getTokenWithCertificate = function(certificate, thumbprint, callback) { | ||
this._log.info('Getting a token via certificate.'); | ||
var authorityUrl = this._authenticationContext._authority; | ||
var jwt; | ||
try { | ||
jwt = this._createJwt(authorityUrl, certificate, thumbprint); | ||
} catch (err) { | ||
callback(err); | ||
return; | ||
} | ||
var oauthParameters = this._createOAuthParameters(OAuth2GrantType.CLIENT_CREDENTIALS); | ||
oauthParameters[OAuth2Parameters.CLIENT_ASSERTION_TYPE] = OAuth2GrantType.JWT_BEARER; | ||
oauthParameters[OAuth2Parameters.CLIENT_ASSERTION] = jwt; | ||
this._getTokenWithCacheWrapper(callback, function(getTokenCompleteCallback) { | ||
this._oauthGetToken(oauthParameters, getTokenCompleteCallback); | ||
}); | ||
}; | ||
module.exports = TokenRequest; |
@@ -24,3 +24,3 @@ /* | ||
var _ = require('underscore'); | ||
var adalIdConstants = require('./constants').AdalIdParameters; | ||
var adalIdConstants = require('./constants').AdalIdParameters; | ||
var fs = require('fs'); | ||
@@ -167,5 +167,9 @@ var os = require('os'); | ||
function convertUrlSafeToRegularBase64EncodedString(str) { | ||
return str.replace('-', '+').replace('_', '/'); | ||
return str.replace(/-/g, '+').replace(/_/g, '/'); | ||
} | ||
function convertRegularToUrlSafeBase64EncodedString(str) { | ||
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); | ||
} | ||
function base64DecodeStringUrlSafe(str) { | ||
@@ -176,2 +180,8 @@ var base64 = convertUrlSafeToRegularBase64EncodedString(str); | ||
function base64EncodeStringUrlSafe(str) { | ||
var base64 = (new Buffer(str, 'utf8').toString('base64')); | ||
var converted = convertRegularToUrlSafeBase64EncodedString(base64); | ||
return converted; | ||
} | ||
module.exports.adalInit = adalInit; | ||
@@ -182,2 +192,4 @@ module.exports.isHttpSuccess = isHttpSuccess; | ||
module.exports.copyUrl = copyUrl; | ||
module.exports.base64DecodeStringUrlSafe = base64DecodeStringUrlSafe; | ||
module.exports.base64DecodeStringUrlSafe = base64DecodeStringUrlSafe; | ||
module.exports.base64EncodeStringUrlSafe = base64EncodeStringUrlSafe; | ||
module.exports.convertRegularToUrlSafeBase64EncodedString = convertRegularToUrlSafeBase64EncodedString; |
@@ -18,3 +18,3 @@ { | ||
}, | ||
"version": "0.1.10", | ||
"version": "0.1.11", | ||
"description": "Windows Azure Active Directory Client Library for node", | ||
@@ -27,2 +27,3 @@ "keywords": [ "node", "azure", "AAD", "adal", "adfs", "oauth" ], | ||
"date-utils": "*", | ||
"jws": "1.x.x", | ||
"node-uuid": "1.4.1", | ||
@@ -29,0 +30,0 @@ "request": ">= 2.9.203", |
@@ -46,3 +46,3 @@ /* | ||
function setupExpectedAuthCodeTokenRequestResponse(httpCode, returnDoc, authorityEndpoint) { | ||
var authEndpoint = authorityEndpoint || cp.evoEndpoint; | ||
var authEndpoint = util.getNockAuthorityHost(authorityEndpoint); | ||
@@ -66,3 +66,3 @@ var queryParameters = {}; | ||
util.matchStandardRequestHeaders(tokenRequest); | ||
util.matchStandardRequestHeaders(tokenRequest); | ||
@@ -69,0 +69,0 @@ return tokenRequest; |
@@ -38,2 +38,3 @@ /* | ||
var AuthenticationContext = adal.AuthenticationContext; | ||
var SelfSignedJwt = testRequire('self-signed-jwt'); | ||
@@ -238,3 +239,59 @@ /** | ||
}); | ||
function updateSelfSignedJwtStubs() { | ||
var savedProto = {}; | ||
savedProto._getDateNow = SelfSignedJwt.prototype._getDateNow; | ||
savedProto._getNewJwtId = SelfSignedJwt.prototype._getNewJwtId; | ||
SelfSignedJwt.prototype._getDateNow = function() { return cp.nowDate; }; | ||
SelfSignedJwt.prototype._getNewJwtId = function() { return cp.jwtId; }; | ||
return savedProto; | ||
} | ||
function resetSelfSignedJwtStubs(saveProto) { | ||
_.extend(SelfSignedJwt.prototype, saveProto); | ||
} | ||
test('cert-happy-path', function(done) { | ||
var saveProto = updateSelfSignedJwtStubs(); | ||
var responseOptions = { noRefresh : true }; | ||
var response = util.createResponse(responseOptions); | ||
var tokenRequest = util.setupExpectedClientAssertionTokenRequestResponse(200, response.wireResponse, cp.authorityTenant); | ||
var context = new AuthenticationContext(cp.authorityTenant); | ||
context.acquireTokenWithClientCertificate(response.resource, cp.clientId, cp.cert, cp.certHash, function (err, tokenResponse) { | ||
resetSelfSignedJwtStubs(saveProto); | ||
tokenRequest.done(); | ||
if (!err) { | ||
assert(util.isMatchTokenResponse(response.cachedResponse, tokenResponse), 'The response did not match what was expected'); | ||
tokenRequest.done(); | ||
} | ||
done(err); | ||
}); | ||
}); | ||
test('cert-bad-cert', function(done) { | ||
var cert = 'gobbledy'; | ||
var context = new AuthenticationContext(cp.authorityTenant); | ||
context.acquireTokenWithClientCertificate(cp.resource, cp.clientId, cert, cp.certHash, function (err) { | ||
assert(err, 'Did not recieve expected error.'); | ||
assert(0 <= err.message.indexOf('Failed to sign JWT'), 'Unexpected error message' + err.message); | ||
done(); | ||
}); | ||
}); | ||
test('cert-bad-thumbprint', function(done) { | ||
var thumbprint = 'gobbledy'; | ||
var context = new AuthenticationContext(cp.authorityTenant); | ||
context.acquireTokenWithClientCertificate(cp.resource, cp.clientId, cp.cert, thumbprint, function (err) { | ||
assert(err, 'Did not recieve expected error.'); | ||
assert(0 <= err.message.indexOf('thumbprint does not match a known format'), 'Unexpected error message' + err.message); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
@@ -83,3 +83,3 @@ /* | ||
function setupExpectedUserNamePasswordRequestResponse(httpCode, returnDoc, authorityEndpoint) { | ||
var authEndpoint = authorityEndpoint || cp.evoEndpoint; | ||
var authEndpoint = util.getNockAuthorityHost(authorityEndpoint); | ||
@@ -86,0 +86,0 @@ var queryParameters = {}; |
@@ -21,2 +21,4 @@ 'use strict'; | ||
var util = {}; | ||
var successResponse = { | ||
@@ -137,4 +139,15 @@ 'access_token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1THdqcHdBSk9NOW4tQSJ9.eyJhdWQiOiIwMDAwMDAwMi0wMDAwLTAwMDAtYzAwMC0wMDAwMDAwMDAwMDAiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC82MmYwMzQ3MS02N2MxLTRjNTAtYjlkMS0xMzQ1MDc5ZDk3NzQvIiwiaWF0IjoxMzc4NjAxMTY4LCJuYmYiOjEzNzg2MDExNjgsImV4cCI6MTM3ODYyOTk2OCwidmVyIjoiMS4wIiwidGlkIjoiNjJmMDM0NzEtNjdjMS00YzUwLWI5ZDEtMTM0NTA3OWQ5Nzc0Iiwib2lkIjoiZjEzMDkzNDEtZDcyMy00YTc1LTk2YzktNGIyMTMzMzk0Mjg3Iiwic3ViIjoiZjEzMDkzNDEtZDcyMy00YTc1LTk2YzktNGIyMTMzMzk0Mjg3IiwiYXBwaWQiOiI1YzI1ZDFiZi1iMjMyLTQwMzUtYjZiOS0yYjdlN2U4MzQ2ZDYiLCJhcHBpZGFjciI6IjEifQ.qXM7f9TTiLApxVMwaSrISQQ6UAnfKvKhoIlN9rB0Eff2VXvIWKGRsclPkMQ5x42BQz2N6pSXEsN-LsNCZlQ76Rc3rVRONzeCYh7q_NXcCJG_d6SJTtV5GBfgqFlgT8UF5rblabbMdOiOrddvJm048hWt2Nm3qD3QjQdPBlD7Ksn-lUR1jEJPIqDaBjGom8RawrZTW6X1cy1Kr8mEYFkxcbU91k_RZUumONep9FTR8gfPkboeD8zyvOy64UeysEtcuaNCfhHSBFcwC8MwjUr5r_T7au7ywAcYDOVgoa7oF_dN1JNweiDoNNZ9tyUS-RY3sa3-gXk77gRxpA4CkpittQ', | ||
var util = {}; | ||
util.getSelfSignedCert = function() { | ||
var privatePem = fs.readFileSync(__dirname + '/self-signed-cert.pem', { encoding : 'utf8'}); | ||
return privatePem; | ||
}; | ||
parameters.certHash = 'C1:5D:EA:86:56:AD:DF:67:BE:80:31:D8:5E:BD:DC:5A:D6:C4:36:E1'; | ||
parameters.nowDate = new Date(1418433646179); | ||
parameters.jwtId = '09841beb-a2c2-4777-a347-34ef055238a8'; | ||
parameters.expectedJwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IndWM3FobGF0MzJlLWdESFlYcjNjV3RiRU51RSJ9.eyJhdWQiOiJodHRwczovL2xvZ2luLndpbmRvd3MubmV0L3JyYW5kYWxsYWFkMS5vbm1pY3Jvc29mdC5jb20vb2F1dGgyL3Rva2VuIiwiaXNzIjoiY2xpZW4mJj8_P3RJZCIsInN1YiI6ImNsaWVuJiY_Pz90SWQiLCJuYmYiOjE0MTg0MzM2NDYsImV4cCI6MTQxODQzNDI0NiwianRpIjoiMDk4NDFiZWItYTJjMi00Nzc3LWEzNDctMzRlZjA1NTIzOGE4In0.dgF0TRlcASgTMp_1dlm8vd7tudr6n40VeuOQGFnz566s3n76WR_jJDBBBKlYeqc9gwCPFOzrLVAJehVYZ3N7YPzVdulf47rLoQdAp8R_p4Q4hdBZuIzfgDWwXjnP9x_NlfzezEYE4r8KTS2g5BBzPmx538AfIdNM93hWIxQySZGWY5UAhTkT1qE1ce1Yjo1M2HqzEJhTg5TTyfrnDtNxFxmzYhSyA9B41lB5kBuJTXUWXPrr-6eG8cEUOS-iiH7YB1Tf4J7_9JQloevTiOrfv4pSp6xLLXm2ntNBg3gaKsGKdYd-3tsCG0mHn7BzL0b-QCLalkUr8KtgtLqkxuAiLQ'; | ||
parameters.cert = util.getSelfSignedCert(); | ||
util.commonParameters = parameters; | ||
@@ -305,3 +318,4 @@ | ||
var tokenRequest = nock(authorityEndpoint) | ||
var authEndpoint = this.getNockAuthorityHost(authorityEndpoint); | ||
var tokenRequest = nock(authEndpoint) | ||
.filteringRequestBody(function(body) { | ||
@@ -341,3 +355,3 @@ return util.filterQueryString(query, body); | ||
var instanceDiscoveryEndpoint = url.resolve(instanceDiscoveryUrl, '/'); | ||
var instanceDiscoveryEndpoint = this.trimPathFromUrl(instanceDiscoveryUrl); | ||
@@ -363,2 +377,3 @@ var discoveryRequest = nock(instanceDiscoveryEndpoint) | ||
var userRealmAuthority = authority || parameters.authority; | ||
userRealmAuthority = this.trimPathFromUrl(userRealmAuthority); | ||
@@ -467,3 +482,15 @@ var userRealmPath = parameters.userRealmPathTemplate.replace('<user>', encodeURIComponent(parameters.username)); | ||
util.setupExpectedClientAssertionTokenRequestResponse = function(httpCode, returnDoc, authorityEndpoint) { | ||
var authEndpoint = authorityEndpoint || parameters.authority; | ||
var queryParameters = {}; | ||
queryParameters['grant_type'] = 'client_credentials'; | ||
queryParameters['client_assertion_type'] = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'; | ||
queryParameters['client_assertion'] = parameters.expectedJwt; | ||
queryParameters['client_id'] = parameters.clientId; | ||
queryParameters['resource'] = parameters.resource; | ||
return util.setupExpectedOAuthResponse(queryParameters, parameters.tokenUrlPath, httpCode, returnDoc, authEndpoint); | ||
}; | ||
function isDateWithinTolerance(date, expectedDate) { | ||
@@ -587,3 +614,12 @@ var expected = expectedDate || new Date(); | ||
util.trimPathFromUrl = function(stringUrl) { | ||
var u = url.parse(stringUrl); | ||
return url.resolve(u, '/'); | ||
}; | ||
util.getNockAuthorityHost = function(authority) { | ||
var authEndpoint = authority || this.commonParameters.evoEndpoint; | ||
return this.trimPathFromUrl(authEndpoint); | ||
}; | ||
module.exports = util; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1057577
64
7504
2
7
19
+ Addedjws@1.x.x
+ Addedbase64url@0.0.61.0.6(transitive)
+ Addedbuffer-equal-constant-time@1.0.1(transitive)
+ Addedcamelcase@1.2.1(transitive)
+ Addedcamelcase-keys@1.0.0(transitive)
+ Addedconcat-stream@1.4.11(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addedecdsa-sig-formatter@1.0.11(transitive)
+ Addedget-stdin@4.0.1(transitive)
+ Addedindent-string@1.2.2(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-finite@1.1.0(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedjwa@1.0.2(transitive)
+ Addedjws@1.0.1(transitive)
+ Addedmap-obj@1.0.1(transitive)
+ Addedmeow@2.0.0(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedobject-assign@1.0.0(transitive)
+ Addedreadable-stream@1.1.14(transitive)
+ Addedrepeating@1.1.3(transitive)
+ Addedstring_decoder@0.10.31(transitive)
+ Addedtypedarray@0.0.7(transitive)