cordova-plugin-ms-adal
Version:
Provides Microsoft Azure Active Directory (ADAL) OAuth client.
322 lines (271 loc) • 13 kB
JavaScript
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
/*global require, Microsoft, Windows, WinJS*/
var Deferred = require('./utility').Utility.Deferred;
var UserInfo = require('./UserInfo');
var isPhone = WinJS.Utilities.isPhone;
var webAuthBrokerContinuationCallback = null;
var successWebAuthStatus = Windows.Security.Authentication.Web.WebAuthenticationStatus.success;
var activationKindWebAuthContinuation = Windows.ApplicationModel.Activation.ActivationKind.webAuthenticationBrokerContinuation;
var AUTH_RESULT_SUCCESS_STATUS = 0;
var OPTIONAL_DISPLAYABLE_ID = Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifierType.optionalDisplayableId;
var ctxCache = {};
function handleAuthResult(win, fail, res) {
if (res.status === AUTH_RESULT_SUCCESS_STATUS) {
win(res);
} else {
fail(res);
}
}
function tryMapUniqueIdToDisplayName(context, uniqueId) {
var cacheItems = toJsArray(context.tokenCache.readItems() || []);
for (var i = 0; i < cacheItems.length; i++) {
try {
if (cacheItems[i].uniqueId === uniqueId) {
return cacheItems[i].displayableId;
}
} catch (e) { }
}
return null;
}
function tryMapDisplayNameToUniqueId(context, displayName) {
var cacheItems = toJsArray(context.tokenCache.readItems() || []);
for (var i = 0; i < cacheItems.length; i++) {
try {
if (cacheItems[i].displayableId === displayName) {
return cacheItems[i].uniqueId;
}
} catch (e) { }
}
return null;
}
function getUserIdentifier(context, userId) {
var uniqueId = tryMapDisplayNameToUniqueId(context, userId);
if (uniqueId !== null) {
return wrapUserId(userId, OPTIONAL_DISPLAYABLE_ID);
}
var displayName = tryMapUniqueIdToDisplayName(context, userId);
if (displayName !== null) {
return wrapUserId(displayName, OPTIONAL_DISPLAYABLE_ID);
}
return wrapUserId(userId, OPTIONAL_DISPLAYABLE_ID);
}
function wrapUserId(userId, type) {
return (userId !== '' && userId != null) ? new Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier(userId, type)
: Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier.anyUser;
}
function toJsArray(arrayLike) {
return Array.prototype.slice.call(arrayLike);
}
var ADALProxy = {
createAsync: function (win, fail, args) {
var authority = args[0];
var validateAuthority = args[1] !== false; // true by default
if (isPhone) {
try {
// WP 8.1
Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.createAsync(authority, validateAuthority).then(function (ctx) {
ctx.useCorporateNetwork = window.ADAL_DEFAULT_USE_CORPORATE_NETWORK === true;
ctxCache[authority] = ctx;
win(ctx);
}, function(e) {
fail(e);
});
} catch (e) {
fail(e);
}
} else {
// Win 8.0 / 8.1
try {
var nativeContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authority, validateAuthority);
nativeContext.useCorporateNetwork = window.ADAL_DEFAULT_USE_CORPORATE_NETWORK === true;
ctxCache[authority] = nativeContext;
win(nativeContext);
} catch (e) {
fail(e);
}
}
},
getOrCreateCtx: function(authority, validateAuthority) {
var d = new Deferred();
validateAuthority = validateAuthority !== false; // true by default
if (typeof ctxCache[authority] !== 'undefined') {
d.resolve(ctxCache[authority]);
} else {
ADALProxy.createAsync(function (ctx) {
d.resolve(ctx);
}, function (err) {
d.reject(err);
}, [authority, validateAuthority]);
}
return d;
},
acquireTokenAsync: function (win, fail, args) {
try {
var authority = args[0];
var validateAuthority = args[1];
var resourceUrl = args[2];
var clientId = args[3];
var redirectUrl = new Windows.Foundation.Uri(args[4]);
var userId = args[5];
var extraQueryParameters = args[6];
var userIdentifier;
ADALProxy.getOrCreateCtx(authority, validateAuthority).then(function (context) {
userIdentifier = getUserIdentifier(context, userId);
if (isPhone) {
// Continuation callback is used when we're running on WindowsPhone which uses
// AuthenticateAndContinue method instead of AuthenticateAsync, which uses different async model
// Continuation callback need to be assigned to Application's 'activated' event.
webAuthBrokerContinuationCallback = function (activationArgs) {
if (activationArgs.detail.kind === activationKindWebAuthContinuation) {
var result = activationArgs.detail.webAuthenticationResult;
if (result.responseStatus == successWebAuthStatus) {
context.continueAcquireTokenAsync(activationArgs.detail);
} else {
fail(result);
}
WinJS.Application.removeEventListener('activated', webAuthBrokerContinuationCallback, true);
}
};
WinJS.Application.addEventListener('activated', webAuthBrokerContinuationCallback, true);
try {
if (typeof userIdentifier !== 'undefined') {
if (typeof extraQueryParameters === 'undefined') {
context.acquireTokenAndContinue(resourceUrl, clientId, redirectUrl, userIdentifier, function (res) {
handleAuthResult(win, fail, res);
});
} else {
context.acquireTokenAndContinue(resourceUrl, clientId, redirectUrl, userIdentifier, extraQueryParameters, function (res) {
handleAuthResult(win, fail, res);
});
}
} else {
context.acquireTokenAndContinue(resourceUrl, clientId, redirectUrl, function (res) {
handleAuthResult(win, fail, res);
});
}
} catch (e) {
fail(e);
}
} else {
if (context.useCorporateNetwork) {
// Try to SSO first
context.acquireTokenAsync(resourceUrl, clientId, Windows.Security.Authentication.Web.WebAuthenticationBroker.getCurrentApplicationCallbackUri(), Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior.never, userIdentifier, extraQueryParameters).then(function (res) {
handleAuthResult(win, function() {
context.acquireTokenAsync(resourceUrl, clientId, Windows.Security.Authentication.Web.WebAuthenticationBroker.getCurrentApplicationCallbackUri(), Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior.always, userIdentifier, extraQueryParameters).then(function (res) {
handleAuthResult(win, fail, res);
}, fail);
}, res);
}, fail);
} else {
context.acquireTokenAsync(resourceUrl, clientId, redirectUrl, Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior.always, userIdentifier, extraQueryParameters).then(function (res) {
handleAuthResult(win, fail, res);
}, fail);
}
}
}, fail);
} catch (e) {
fail(e);
}
},
acquireTokenSilentAsync: function (win, fail, args) {
try {
var authority = args[0];
var validateAuthority = args[1];
var resourceUrl = args[2];
var clientId = args[3];
var userId = args[4];
ADALProxy.getOrCreateCtx(authority, validateAuthority).then(function (context) {
var userIdentifier = getUserIdentifier(context, userId);
context.acquireTokenSilentAsync(resourceUrl, clientId, userIdentifier).then(function (res) {
handleAuthResult(win, fail, res);
}, fail);
}, fail);
} catch (e) {
fail(e);
}
},
tokenCacheClear: function (win, fail, args) {
try {
var authority = args[0];
var validateAuthority = args[1];
ADALProxy.getOrCreateCtx(authority, validateAuthority).then(function (context) {
context.tokenCache.clear();
ctxCache = {};
win();
}, fail);
} catch (e) {
fail(e);
}
},
tokenCacheReadItems: function (win, fail, args) {
try {
var authority = args[0];
var validateAuthority = args[1];
ADALProxy.getOrCreateCtx(authority, validateAuthority).then(function (context) {
win(toJsArray(context.tokenCache.readItems() || []).map(function (item) {
var copy = {};
try {
copy.accessToken = item.accessToken;
} catch (e) { }
try {
copy.authority = item.authority;
} catch (e) { }
try {
copy.clientId = item.clientId;
} catch (e) { }
try {
copy.displayableId = item.displayableId;
} catch (e) { }
try {
copy.expiresOn = item.expiresOn;
} catch (e) { }
try {
copy.isMultipleResourceRefreshToken = item.isMultipleResourceRefreshToken;
} catch (e) { }
try {
copy.resource = item.resource;
} catch (e) { }
try {
copy.tenantId = item.tenantId;
} catch (e) { }
try {
copy.idToken = item.idToken;
copy.userInfo = UserInfo.fromJWT(copy.idToken || copy.accessToken);
} catch (e) { }
return copy;
}));
}, fail);
} catch (e) {
fail(e);
}
},
tokenCacheDeleteItem: function (win, fail, args) {
try {
var contextAuthority = args[0];
var validateAuthority = args[1];
var itemAuthority = args[2];
var itemResource = args[3];
var itemClientId = args[4];
var itemUserId = args[5];
var itemIsMultipleResourceRefreshToken = args[6];
ADALProxy.getOrCreateCtx(contextAuthority, validateAuthority).then(function (context) {
var allItems = toJsArray(context.tokenCache.readItems() || []);
for (var i = 0; i < allItems.length; i++) {
if (allItems[i].clientId === itemClientId
&& allItems[i].resource === itemResource
&& allItems[i].uniqueId === itemUserId
&& allItems[i].authority === itemAuthority
&& allItems[i].isMultipleResourceRefreshToken === itemIsMultipleResourceRefreshToken) {
context.tokenCache.deleteItem(allItems[i]);
win();
return;
}
}
fail('No such item found');
}, fail);
} catch (e) {
fail(e);
}
}
};
require("cordova/exec/proxy").add("ADALProxy", ADALProxy);