diff --git a/README.md b/README.md
index be12f3d0..94710879 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ This library is optimized for working together with AngularJS.
## The Library
-This is a GA released version. The current version is **1.0.9**.
+This is a GA released version. The current version is **1.0.10**.
You have multiple ways of getting ADAL JS:
@@ -18,10 +18,10 @@ Via NPM:
Via CDN:
-
-
+
+
-CDN will be updated to latest version 1.0.9.
+CDN will be updated to latest version 1.0.10.
Via Bower:
diff --git a/bower.json b/bower.json
index 7687ca65..79e7339e 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "adal-angular",
- "version": "1.0.9",
+ "version": "1.0.10",
"homepage": "https://github.com/AzureAD/azure-activedirectory-library-for-js",
"authors": [
"MSOpentech"
diff --git a/changelog.txt b/changelog.txt
index 87a977fc..5d9fdade 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,7 @@
+Version 1.0.10
+==========================
+Fixing infinite loop when refreshing tokens, adding extensibility for specifying anonymous endpoints
+
Version 1.0.9
==========================
Adding events for state mismatch and error responses. Fix for token renewal for app's backend. Making library available on NPM
diff --git a/dist/adal-angular.min.js b/dist/adal-angular.min.js
index 5ff878b4..c7bbc283 100644
--- a/dist/adal-angular.min.js
+++ b/dist/adal-angular.min.js
@@ -1,2 +1,2 @@
-/*! adal-angular v1.0.9 2016-04-04 */
-"use strict";"undefined"!=typeof module&&module.exports&&(module.exports.inject=function(a){return new AuthenticationContext(a)}),function(){if(angular){var a=angular.module("AdalAngular",[]);a.provider("adalAuthenticationService",function(){var a=null,b={isAuthenticated:!1,userName:"",loginError:"",profile:""},c=function(c){var d=a.getCachedToken(c);b.isAuthenticated=null!==d&&d.length>0;var e=a.getCachedUser()||{userName:""};b.userName=e.userName,b.profile=e.profile,b.loginError=a.getLoginError()};this.init=function(b,d){if(!b)throw new Error("You must set configOptions, when calling init");var e=window.location.hash,f=window.location.href;e&&(f=f.replace(e,"")),b.redirectUri=b.redirectUri||f,b.postLogoutRedirectUri=b.postLogoutRedirectUri||f,d&&d.interceptors&&d.interceptors.push("ProtectedResourceInterceptor"),a=new AuthenticationContext(b),c(a.config.loginResource)},this.$get=["$rootScope","$window","$q","$location","$timeout",function(d,e,f,g,h){function i(a,b){return b.requireADLogin?a.requireADLogin!==!1:!!a.requireADLogin}var j=function(){var f=e.location.hash;if(a.isCallback(f)){var i=a.getRequestInfo(f);if(a.saveTokenFromHash(i),g.$$html5?e.location=e.location.origin+e.location.pathname:e.location.hash="",i.requestType!==a.REQUEST_TYPE.LOGIN&&(a._renewActive=!1,a.callback=e.parent.AuthenticationContext().callback,i.requestType===a.REQUEST_TYPE.RENEW_TOKEN&&(a.callback=e.parent.callBackMappedToRenewStates[i.stateResponse])),i.stateMatch)if("function"==typeof a.callback){if(i.requestType===a.REQUEST_TYPE.RENEW_TOKEN){if(i.parameters.access_token)return void a.callback(a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION),i.parameters.access_token);if(i.parameters.id_token)return void a.callback(a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION),i.parameters.id_token)}}else c(a.config.loginResource),b.userName?(h(function(){c(a.config.loginResource),d.userInfo=b;var e=a._getItem(a.CONSTANTS.STORAGE.START_PAGE);if(e){var f=a._getItem(a.CONSTANTS.STORAGE.START_PAGE_PARAMS);if(f){var h=JSON.parse(f);g.url(e).search(h)}else g.url(e)}},1),d.$broadcast("adal:loginSuccess")):d.$broadcast("adal:loginFailure",a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION));else d.$broadcast("adal:stateMismatch",a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION))}else c(a.config.loginResource),a._renewActive||b.isAuthenticated||!b.userName||(a._renewActive=!0,a.acquireToken(a.config.loginResource,function(a,c){a?d.$broadcast("adal:loginFailure","auto renew failure"):c&&(b.isAuthenticated=!0)}));h(function(){c(a.config.loginResource),d.userInfo=b},1)},k=function(){a.info("Login event for:"+g.$$url),a.config&&a.config.localLoginUrl?g.path(a.config.localLoginUrl):(a._saveItem(a.CONSTANTS.STORAGE.START_PAGE,g.$$url),a.info("Start login at:"+window.location.href),d.$broadcast("adal:loginRedirect"),a.login())},l=function(c,d){d&&d.$$route&&i(d.$$route,a.config)&&(b.isAuthenticated||a._renewActive||(a.info("Route change event for:"+g.$$url),k()))},m=function(c,d,e,f,h){d&&i(d,a.config)&&(b.isAuthenticated||a._renewActive||(g.$$url=d.url,a._saveItem(a.CONSTANTS.STORAGE.START_PAGE_PARAMS,JSON.stringify(e)),a.info("State change event for:"+g.$$url),k()))};return d.$on("$routeChangeStart",l),d.$on("$stateChangeStart",m),d.$on("$locationChangeStart",j),c(a.config.loginResource),d.userInfo=b,{config:a.config,login:function(){a.login()},loginInProgress:function(){return a.loginInProgress()},logOut:function(){a.logOut()},getCachedToken:function(b){return a.getCachedToken(b)},userInfo:b,acquireToken:function(b){var c=f.defer();return a._renewActive=!0,a.acquireToken(b,function(d,e){a._renewActive=!1,d?(a.error("Error when acquiring token for resource: "+b,d),c.reject(d)):c.resolve(e)}),c.promise},getUser:function(){var b=f.defer();return a.getUser(function(c,d){c?(a.error("Error when getting user",c),b.reject(c)):b.resolve(d)}),b.promise},getResourceForEndpoint:function(b){return a.getResourceForEndpoint(b)},clearCache:function(){a.clearCache()},clearCacheForResource:function(b){a.clearCacheForResource(b)},info:function(b){a.info(b)},verbose:function(b){a.verbose(b)}}}]}),a.factory("ProtectedResourceInterceptor",["adalAuthenticationService","$q","$rootScope",function(a,b,c){return{request:function(c){if(c){c.headers=c.headers||{};var d=a.getResourceForEndpoint(c.url);if(null===d)return c;var e=a.getCachedToken(d);if(e)return a.info("Token is avaliable for this url "+c.url),c.headers.Authorization="Bearer "+e,c;if(a.loginInProgress())return a.info("login already start."),b.reject("login in progress, cancelling the request");var f=b.defer();return a.acquireToken(d).then(function(b){a.verbose("Token is avaliable"),c.headers.Authorization="Bearer "+b,f.resolve(c)},function(a){f.reject(a)}),f.promise}},responseError:function(d){if(a.info("Getting error in the response"),d){if(401===d.status){var e=a.getResourceForEndpoint(d.config.url);a.clearCacheForResource(e),c.$broadcast("adal:notAuthorized",d,e)}else c.$broadcast("adal:errorResponse",d);return b.reject(d)}}}}])}else console.error("Angular.JS is not included")}();
\ No newline at end of file
+/*! adal-angular v1.0.10 2016-05-09 */
+"use strict";"undefined"!=typeof module&&module.exports&&(module.exports.inject=function(a){return new AuthenticationContext(a)}),function(){if(angular){var a=angular.module("AdalAngular",[]);a.provider("adalAuthenticationService",function(){var a=null,b={isAuthenticated:!1,userName:"",loginError:"",profile:""},c=function(c){var d=a.getCachedToken(c);b.isAuthenticated=null!==d&&d.length>0;var e=a.getCachedUser()||{userName:""};b.userName=e.userName,b.profile=e.profile,b.loginError=a.getLoginError()};this.init=function(b,d){if(!b)throw new Error("You must set configOptions, when calling init");var e=window.location.hash,f=window.location.href;e&&(f=f.replace(e,"")),b.redirectUri=b.redirectUri||f,b.postLogoutRedirectUri=b.postLogoutRedirectUri||f,d&&d.interceptors&&d.interceptors.push("ProtectedResourceInterceptor"),a=new AuthenticationContext(b),c(a.config.loginResource)},this.$get=["$rootScope","$window","$q","$location","$timeout",function(d,e,f,g,h){function i(a,b){return b.requireADLogin?a.requireADLogin!==!1:!!a.requireADLogin}function j(b){if(a.config&&a.config.anonymousEndpoints)for(var c=0;c-1)return!0;return!1}var k=function(){var f=e.location.hash;if(a.isCallback(f)){var i=a.getRequestInfo(f);if(a.saveTokenFromHash(i),g.$$html5?e.location=e.location.origin+e.location.pathname:e.location.hash="",i.requestType!==a.REQUEST_TYPE.LOGIN&&(a.callback=e.parent.AuthenticationContext().callback,i.requestType===a.REQUEST_TYPE.RENEW_TOKEN&&(a.callback=e.parent.callBackMappedToRenewStates[i.stateResponse])),i.stateMatch)if("function"==typeof a.callback){if(i.requestType===a.REQUEST_TYPE.RENEW_TOKEN){if(i.parameters.access_token)return void a.callback(a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION),i.parameters.access_token);if(i.parameters.id_token)return void a.callback(a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION),i.parameters.id_token);if(i.parameters.error)return a.callback(a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION),null),void(a._renewFailed=!0)}}else c(a.config.loginResource),b.userName?(h(function(){c(a.config.loginResource),d.userInfo=b;var e=a._getItem(a.CONSTANTS.STORAGE.START_PAGE);if(e){var f=a._getItem(a.CONSTANTS.STORAGE.START_PAGE_PARAMS);if(f){var h=JSON.parse(f);g.url(e).search(h)}else g.url(e)}},1),d.$broadcast("adal:loginSuccess")):d.$broadcast("adal:loginFailure",a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION));else d.$broadcast("adal:stateMismatch",a._getItem(a.CONSTANTS.STORAGE.ERROR_DESCRIPTION))}else c(a.config.loginResource),b.isAuthenticated||!b.userName||a._renewActive||a._renewFailed||(a._renewActive=!0,a.acquireToken(a.config.loginResource,function(c,e){a._renewActive=!1,c?d.$broadcast("adal:loginFailure","auto renew failure"):e&&(b.isAuthenticated=!0)}));h(function(){c(a.config.loginResource),d.userInfo=b},1)},l=function(){a.info("Login event for:"+g.$$url),a.config&&a.config.localLoginUrl?g.path(a.config.localLoginUrl):(a._saveItem(a.CONSTANTS.STORAGE.START_PAGE,g.$$url),a.info("Start login at:"+window.location.href),d.$broadcast("adal:loginRedirect"),a.login())},m=function(c,d){d&&d.$$route&&(i(d.$$route,a.config)?b.isAuthenticated||a._renewActive||(a.info("Route change event for:"+g.$$url),l()):d.$$route.templateUrl&&!j(d.$$route.templateUrl)&&a.config.anonymousEndpoints.push(d.$$route.templateUrl))},n=function(c,d,e,f,h){d&&(i(d,a.config)?b.isAuthenticated||a._renewActive||(g.$$url=d.url,a._saveItem(a.CONSTANTS.STORAGE.START_PAGE_PARAMS,JSON.stringify(e)),a.info("State change event for:"+g.$$url),l()):d.templateUrl&&!j(d.templateUrl)&&a.config.anonymousEndpoints.push(d.templateUrl))};return d.$on("$routeChangeStart",m),d.$on("$stateChangeStart",n),d.$on("$locationChangeStart",k),c(a.config.loginResource),d.userInfo=b,{config:a.config,login:function(){a.login()},loginInProgress:function(){return a.loginInProgress()},logOut:function(){a.logOut()},getCachedToken:function(b){return a.getCachedToken(b)},userInfo:b,acquireToken:function(b){var c=f.defer();return a._renewActive=!0,a.acquireToken(b,function(d,e){a._renewActive=!1,d?(a.error("Error when acquiring token for resource: "+b,d),c.reject(d)):c.resolve(e)}),c.promise},getUser:function(){var b=f.defer();return a.getUser(function(c,d){c?(a.error("Error when getting user",c),b.reject(c)):b.resolve(d)}),b.promise},getResourceForEndpoint:function(b){return a.getResourceForEndpoint(b)},clearCache:function(){a.clearCache()},clearCacheForResource:function(b){a.clearCacheForResource(b)},info:function(b){a.info(b)},verbose:function(b){a.verbose(b)}}}]}),a.factory("ProtectedResourceInterceptor",["adalAuthenticationService","$q","$rootScope",function(a,b,c){return{request:function(c){if(c){c.headers=c.headers||{};var d=a.getResourceForEndpoint(c.url);if(a.verbose("Url: "+c.url+" maps to resource: "+d),null===d)return c;var e=a.getCachedToken(d);if(e)return a.info("Token is avaliable for this url "+c.url),c.headers.Authorization="Bearer "+e,c;if(a.loginInProgress())return a.info("login already start."),b.reject("login in progress, cancelling the request");var f=b.defer();return a.acquireToken(d).then(function(b){a.verbose("Token is avaliable"),c.headers.Authorization="Bearer "+b,f.resolve(c)},function(a){f.reject(a)}),f.promise}},responseError:function(d){if(a.info("Getting error in the response"),d){if(401===d.status){var e=a.getResourceForEndpoint(d.config.url);a.clearCacheForResource(e),c.$broadcast("adal:notAuthorized",d,e)}else c.$broadcast("adal:errorResponse",d);return b.reject(d)}}}}])}else console.error("Angular.JS is not included")}();
\ No newline at end of file
diff --git a/dist/adal.min.js b/dist/adal.min.js
index 28047928..9f99a40a 100644
--- a/dist/adal.min.js
+++ b/dist/adal.min.js
@@ -1,2 +1,2 @@
-/*! adal-angular v1.0.9 2016-04-04 */
-"use strict";var Logging={level:0,log:function(){}},AuthenticationContext;"undefined"!=typeof module&&module.exports&&(module.exports.inject=function(a){return new AuthenticationContext(a)}),AuthenticationContext=function(a){if(this.REQUEST_TYPE={LOGIN:"LOGIN",RENEW_TOKEN:"RENEW_TOKEN",UNKNOWN:"UNKNOWN"},this.CONSTANTS={ACCESS_TOKEN:"access_token",EXPIRES_IN:"expires_in",ID_TOKEN:"id_token",ERROR_DESCRIPTION:"error_description",SESSION_STATE:"session_state",STORAGE:{TOKEN_KEYS:"adal.token.keys",ACCESS_TOKEN_KEY:"adal.access.token.key",EXPIRATION_KEY:"adal.expiration.key",START_PAGE:"adal.start.page",START_PAGE_PARAMS:"adal.start.page.params",STATE_LOGIN:"adal.state.login",STATE_RENEW:"adal.state.renew",STATE_RENEW_RESOURCE:"adal.state.renew.resource",NONCE_IDTOKEN:"adal.nonce.idtoken",SESSION_STATE:"adal.session.state",USERNAME:"adal.username",IDTOKEN:"adal.idtoken",ERROR:"adal.error",ERROR_DESCRIPTION:"adal.error.description",LOGIN_REQUEST:"adal.login.request",LOGIN_ERROR:"adal.login.error"},RESOURCE_DELIMETER:"|",ERR_MESSAGES:{NO_TOKEN:"User is not authorized"},LOGGING_LEVEL:{ERROR:0,WARN:1,INFO:2,VERBOSE:3},LEVEL_STRING_MAP:{0:"ERROR:",1:"WARNING:",2:"INFO:",3:"VERBOSE:"}},AuthenticationContext.prototype._singletonInstance)return AuthenticationContext.prototype._singletonInstance;if(AuthenticationContext.prototype._singletonInstance=this,this.instance="https://login.microsoftonline.com/",this.config={},this.callback=null,this.popUp=!1,this._user=null,this._activeRenewals={},this._loginInProgress=!1,this._renewStates=[],window.callBackMappedToRenewStates={},window.callBacksMappedToRenewStates={},a.displayCall&&"function"!=typeof a.displayCall)throw new Error("displayCall is not a function");if(!a.clientId)throw new Error("clientId is required");a.correlationId||(a.correlationId=this._guid()),this.config=this._cloneConfig(a),this.config.loginResource||(this.config.loginResource=this.config.clientId),this.config.redirectUri||(this.config.redirectUri=window.location.href)},AuthenticationContext.prototype.login=function(){var a=this._guid();this.config.state=a,this._idTokenNonce=this._guid(),this.verbose("Expected state: "+a+" startPage:"+window.location),this._saveItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST,window.location),this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR,""),this._saveItem(this.CONSTANTS.STORAGE.STATE_LOGIN,a),this._saveItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN,this._idTokenNonce),this._saveItem(this.CONSTANTS.STORAGE.ERROR,""),this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION,"");var b=this._getNavigateUrl("id_token",null)+"&nonce="+encodeURIComponent(this._idTokenNonce);this.frameCallInProgress=!1,this._loginInProgress=!0,this.config.displayCall?this.config.displayCall(b):this.promptUser(b)},AuthenticationContext.prototype.loginInProgress=function(){return this._loginInProgress},AuthenticationContext.prototype._hasResource=function(a){var b=this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS);return b&&!this._isEmpty(b)&&b.indexOf(a+this.CONSTANTS.RESOURCE_DELIMETER)>-1},AuthenticationContext.prototype.getCachedToken=function(a){if(!this._hasResource(a))return null;var b=this._getItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY+a),c=this._getItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY+a),d=this.config.expireOffsetSeconds||120;return c&&c>this._now()+d?b:(this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY+a,""),this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY+a,0),null)},AuthenticationContext.prototype.getCachedUser=function(){if(this._user)return this._user;var a=this._getItem(this.CONSTANTS.STORAGE.IDTOKEN);return this._user=this._createUser(a),this._user},AuthenticationContext.prototype.registerCallback=function(a,b,c){this._activeRenewals[b]=a,window.callBacksMappedToRenewStates[a]||(window.callBacksMappedToRenewStates[a]=[]);var d=this;window.callBacksMappedToRenewStates[a].push(c),window.callBackMappedToRenewStates[a]||(window.callBackMappedToRenewStates[a]=function(c,e){for(var f=0;f-1){var a=this._user.userName.split("@");return a[a.length-1]}return""},AuthenticationContext.prototype._createUser=function(a){var b=null,c=this._extractIdToken(a);return c&&c.hasOwnProperty("aud")&&(c.aud.toLowerCase()===this.config.clientId.toLowerCase()?(b={userName:"",profile:c},c.hasOwnProperty("upn")?b.userName=c.upn:c.hasOwnProperty("email")&&(b.userName=c.email)):this.warn("IdToken has invalid aud field")),b},AuthenticationContext.prototype._getHash=function(a){return a.indexOf("#/")>-1?a=a.substring(a.indexOf("#/")+2):a.indexOf("#")>-1&&(a=a.substring(1)),a},AuthenticationContext.prototype.isCallback=function(a){a=this._getHash(a);var b=this._deserialize(a);return b.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION)||b.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN)||b.hasOwnProperty(this.CONSTANTS.ID_TOKEN)},AuthenticationContext.prototype.getLoginError=function(){return this._getItem(this.CONSTANTS.STORAGE.LOGIN_ERROR)},AuthenticationContext.prototype.getRequestInfo=function(a){a=this._getHash(a);var b=this._deserialize(a),c={valid:!1,parameters:{},stateMatch:!1,stateResponse:"",requestType:this.REQUEST_TYPE.UNKNOWN};if(b&&(c.parameters=b,b.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION)||b.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN)||b.hasOwnProperty(this.CONSTANTS.ID_TOKEN))){c.valid=!0;var d="";if(!b.hasOwnProperty("state"))return this.warn("No state returned"),c;if(this.verbose("State: "+b.state),d=b.state,c.stateResponse=d,d===this._getItem(this.CONSTANTS.STORAGE.STATE_LOGIN))return c.requestType=this.REQUEST_TYPE.LOGIN,c.stateMatch=!0,c;if(!c.stateMatch&&window.parent&&window.parent.AuthenticationContext())for(var e=window.parent.AuthenticationContext()._renewStates,f=0;f-1&&b+1-1)return this.config.endpoints[b];return a.indexOf("http://")>-1||a.indexOf("https://")>-1?this._getHostFromUri(a)===this._getHostFromUri(this.config.redirectUri)?this.config.loginResource:null:this.config.loginResource},AuthenticationContext.prototype._getHostFromUri=function(a){var b=String(a).replace(/^(https?:)\/\//,"");return b=b.split("/")[0]},AuthenticationContext.prototype.handleWindowCallback=function(){var a=window.location.hash;if(this.isCallback(a)){var b=this.getRequestInfo(a);this.info("Returned from redirect url"),this.saveTokenFromHash(b);var c=null;if(b.requestType===this.REQUEST_TYPE.RENEW_TOKEN&&window.parent?(this.verbose("Window is in iframe"),c=window.parent.callBackMappedToRenewStates[b.stateResponse],window.src=""):window&&window.oauth2Callback&&(this.verbose("Window is redirecting"),c=this.callback),window.location.hash="",window.location=this._getItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST),b.requestType===this.REQUEST_TYPE.RENEW_TOKEN)return void c(this._getItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION),b.parameters[this.CONSTANTS.ACCESS_TOKEN]||b.parameters[this.CONSTANTS.ID_TOKEN])}},AuthenticationContext.prototype._getNavigateUrl=function(a,b){var c="common";this.config.tenant&&(c=this.config.tenant),this.config.instance&&(this.instance=this.config.instance);var d=this.instance+c+"/oauth2/authorize"+this._serialize(a,this.config,b)+this._addLibMetadata();return this.info("Navigate url:"+d),d},AuthenticationContext.prototype._extractIdToken=function(a){var b=this._decodeJwt(a);if(!b)return null;try{var c=b.JWSPayload,d=this._base64DecodeStringUrlSafe(c);return d?JSON.parse(d):(this.info("The returned id_token could not be base64 url safe decoded."),null)}catch(e){this.error("The returned id_token could not be decoded",e)}return null},AuthenticationContext.prototype._extractUserName=function(a){try{var b=this._extractIdToken(a);if(b){if(b.hasOwnProperty("upn"))return b.upn;if(b.hasOwnProperty("email"))return b.email}}catch(c){this.error("The returned id_token could not be decoded",c)}return null},AuthenticationContext.prototype._base64DecodeStringUrlSafe=function(a){return a=a.replace(/-/g,"+").replace(/_/g,"/"),window.atob?decodeURIComponent(escape(window.atob(a))):decodeURIComponent(escape(this._decode(a)))},AuthenticationContext.prototype._decode=function(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";a=String(a).replace(/=+$/,"");var c=a.length;if(c%4===1)throw new Error("The token to be decoded is not correctly encoded.");for(var d,e,f,g,h,i,j,k,l="",m=0;c>m;m+=4){if(d=b.indexOf(a.charAt(m)),e=b.indexOf(a.charAt(m+1)),f=b.indexOf(a.charAt(m+2)),g=b.indexOf(a.charAt(m+3)),m+2===c-1){h=d<<18|e<<12|f<<6,i=h>>16&255,j=h>>8&255,l+=String.fromCharCode(i,j);break}if(m+1===c-1){h=d<<18|e<<12,i=h>>16&255,l+=String.fromCharCode(i);break}h=d<<18|e<<12|f<<6|g,i=h>>16&255,j=h>>8&255,k=255&h,l+=String.fromCharCode(i,j,k)}return l},AuthenticationContext.prototype._decodeJwt=function(a){if(this._isEmpty(a))return null;var b=/^([^\.\s]*)\.([^\.\s]+)\.([^\.\s]*)$/,c=b.exec(a);if(!c||c.length<4)return this.warn("The returned id_token is not parseable."),null;var d={header:c[1],JWSPayload:c[2],JWSSig:c[3]};return d},AuthenticationContext.prototype._convertUrlSafeToRegularBase64EncodedString=function(a){return a.replace("-","+").replace("_","/")},AuthenticationContext.prototype._serialize=function(a,b,c){var d=[];return null!==b&&(d.push("?response_type="+a),d.push("client_id="+encodeURIComponent(b.clientId)),c&&d.push("resource="+encodeURIComponent(c)),d.push("redirect_uri="+encodeURIComponent(b.redirectUri)),d.push("state="+encodeURIComponent(b.state)),b.hasOwnProperty("slice")&&d.push("slice="+encodeURIComponent(b.slice)),b.hasOwnProperty("extraQueryParameter")&&d.push(b.extraQueryParameter),b.correlationId&&d.push("client-request-id="+encodeURIComponent(b.correlationId))),d.join("&")},AuthenticationContext.prototype._deserialize=function(a){var b,c=/\+/g,d=/([^&=]+)=?([^&]*)/g,e=function(a){return decodeURIComponent(a.replace(c," "))},f={};for(b=d.exec(a);b;)f[e(b[1])]=e(b[2]),b=d.exec(a);return f},AuthenticationContext.prototype._guid=function(){for(var a="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx",b="0123456789abcdef",c=0,d="",e=0;36>e;e++)"-"!==a[e]&&"4"!==a[e]&&(c=16*Math.random()|0),"x"===a[e]?d+=b[c]:"y"===a[e]?(c&=3,c|=8,d+=b[c]):d+=a[e];return d},AuthenticationContext.prototype._expiresIn=function(a){return this._now()+parseInt(a,10)},AuthenticationContext.prototype._now=function(){return Math.round((new Date).getTime()/1e3)},AuthenticationContext.prototype._addAdalFrame=function(a){if("undefined"!=typeof a){this.info("Add adal frame to document:"+a);var b=document.getElementById(a);if(!b){if(document.createElement&&document.documentElement&&(window.opera||-1===window.navigator.userAgent.indexOf("MSIE 5.0"))){var c=document.createElement("iframe");c.setAttribute("id",a),c.style.visibility="hidden",c.style.position="absolute",c.style.width=c.style.height=c.borderWidth="0px",b=document.getElementsByTagName("body")[0].appendChild(c)}else document.body&&document.body.insertAdjacentHTML&&document.body.insertAdjacentHTML("beforeEnd",'');window.frames&&window.frames[a]&&(b=window.frames[a])}return b}},AuthenticationContext.prototype._saveItem=function(a,b){return this.config&&this.config.cacheLocation&&"localStorage"===this.config.cacheLocation?this._supportsLocalStorage()?(localStorage.setItem(a,b),!0):(this.info("Local storage is not supported"),!1):this._supportsSessionStorage()?(sessionStorage.setItem(a,b),!0):(this.info("Session storage is not supported"),!1)},AuthenticationContext.prototype._getItem=function(a){return this.config&&this.config.cacheLocation&&"localStorage"===this.config.cacheLocation?this._supportsLocalStorage()?localStorage.getItem(a):(this.info("Local storage is not supported"),null):this._supportsSessionStorage()?sessionStorage.getItem(a):(this.info("Session storage is not supported"),null)},AuthenticationContext.prototype._supportsLocalStorage=function(){try{return"localStorage"in window&&window.localStorage}catch(a){return!1}},AuthenticationContext.prototype._supportsSessionStorage=function(){try{return"sessionStorage"in window&&window.sessionStorage}catch(a){return!1}},AuthenticationContext.prototype._cloneConfig=function(a){if(null===a||"object"!=typeof a)return a;var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b},AuthenticationContext.prototype._addLibMetadata=function(){return"&x-client-SKU=Js&x-client-Ver="+this._libVersion()},AuthenticationContext.prototype.log=function(a,b,c){if(a<=Logging.level){var d=this.config.correlationId,e=(new Date).toUTCString(),f=e+":"+d+"-"+this._libVersion()+"-"+this.CONSTANTS.LEVEL_STRING_MAP[a]+" "+b;c&&(f+="\nstack:\n"+c.stack),Logging.log(f)}},AuthenticationContext.prototype.error=function(a,b){this.log(this.CONSTANTS.LOGGING_LEVEL.ERROR,a,b)},AuthenticationContext.prototype.warn=function(a){this.log(this.CONSTANTS.LOGGING_LEVEL.WARN,a,null)},AuthenticationContext.prototype.info=function(a){this.log(this.CONSTANTS.LOGGING_LEVEL.INFO,a,null)},AuthenticationContext.prototype.verbose=function(a){this.log(this.CONSTANTS.LOGGING_LEVEL.VERBOSE,a,null)},AuthenticationContext.prototype._libVersion=function(){return"1.0.9"};
\ No newline at end of file
+/*! adal-angular v1.0.10 2016-05-09 */
+"use strict";var Logging={level:0,log:function(){}},AuthenticationContext;"undefined"!=typeof module&&module.exports&&(module.exports.inject=function(a){return new AuthenticationContext(a)}),AuthenticationContext=function(a){if(this.REQUEST_TYPE={LOGIN:"LOGIN",RENEW_TOKEN:"RENEW_TOKEN",UNKNOWN:"UNKNOWN"},this.CONSTANTS={ACCESS_TOKEN:"access_token",EXPIRES_IN:"expires_in",ID_TOKEN:"id_token",ERROR_DESCRIPTION:"error_description",SESSION_STATE:"session_state",STORAGE:{TOKEN_KEYS:"adal.token.keys",ACCESS_TOKEN_KEY:"adal.access.token.key",EXPIRATION_KEY:"adal.expiration.key",START_PAGE:"adal.start.page",START_PAGE_PARAMS:"adal.start.page.params",STATE_LOGIN:"adal.state.login",STATE_RENEW:"adal.state.renew",STATE_RENEW_RESOURCE:"adal.state.renew.resource",NONCE_IDTOKEN:"adal.nonce.idtoken",SESSION_STATE:"adal.session.state",USERNAME:"adal.username",IDTOKEN:"adal.idtoken",ERROR:"adal.error",ERROR_DESCRIPTION:"adal.error.description",LOGIN_REQUEST:"adal.login.request",LOGIN_ERROR:"adal.login.error"},RESOURCE_DELIMETER:"|",ERR_MESSAGES:{NO_TOKEN:"User is not authorized"},LOGGING_LEVEL:{ERROR:0,WARN:1,INFO:2,VERBOSE:3},LEVEL_STRING_MAP:{0:"ERROR:",1:"WARNING:",2:"INFO:",3:"VERBOSE:"}},AuthenticationContext.prototype._singletonInstance)return AuthenticationContext.prototype._singletonInstance;if(AuthenticationContext.prototype._singletonInstance=this,this.instance="https://login.microsoftonline.com/",this.config={},this.callback=null,this.popUp=!1,this._user=null,this._activeRenewals={},this._loginInProgress=!1,this._renewStates=[],window.callBackMappedToRenewStates={},window.callBacksMappedToRenewStates={},a.displayCall&&"function"!=typeof a.displayCall)throw new Error("displayCall is not a function");if(!a.clientId)throw new Error("clientId is required");a.correlationId||(a.correlationId=this._guid()),this.config=this._cloneConfig(a),this.config.loginResource||(this.config.loginResource=this.config.clientId),this.config.redirectUri||(this.config.redirectUri=window.location.href)},AuthenticationContext.prototype.login=function(){var a=this._guid();this.config.state=a,this._idTokenNonce=this._guid(),this.verbose("Expected state: "+a+" startPage:"+window.location),this._saveItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST,window.location),this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR,""),this._saveItem(this.CONSTANTS.STORAGE.STATE_LOGIN,a),this._saveItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN,this._idTokenNonce),this._saveItem(this.CONSTANTS.STORAGE.ERROR,""),this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION,"");var b=this._getNavigateUrl("id_token",null)+"&nonce="+encodeURIComponent(this._idTokenNonce);this.frameCallInProgress=!1,this._loginInProgress=!0,this.config.displayCall?this.config.displayCall(b):this.promptUser(b)},AuthenticationContext.prototype.loginInProgress=function(){return this._loginInProgress},AuthenticationContext.prototype._hasResource=function(a){var b=this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS);return b&&!this._isEmpty(b)&&b.indexOf(a+this.CONSTANTS.RESOURCE_DELIMETER)>-1},AuthenticationContext.prototype.getCachedToken=function(a){if(!this._hasResource(a))return null;var b=this._getItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY+a),c=this._getItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY+a),d=this.config.expireOffsetSeconds||120;return c&&c>this._now()+d?b:(this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY+a,""),this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY+a,0),null)},AuthenticationContext.prototype.getCachedUser=function(){if(this._user)return this._user;var a=this._getItem(this.CONSTANTS.STORAGE.IDTOKEN);return this._user=this._createUser(a),this._user},AuthenticationContext.prototype.registerCallback=function(a,b,c){this._activeRenewals[b]=a,window.callBacksMappedToRenewStates[a]||(window.callBacksMappedToRenewStates[a]=[]);var d=this;window.callBacksMappedToRenewStates[a].push(c),window.callBackMappedToRenewStates[a]||(window.callBackMappedToRenewStates[a]=function(c,e){for(var f=0;f-1){var a=this._user.userName.split("@");return a[a.length-1]}return""},AuthenticationContext.prototype._createUser=function(a){var b=null,c=this._extractIdToken(a);return c&&c.hasOwnProperty("aud")&&(c.aud.toLowerCase()===this.config.clientId.toLowerCase()?(b={userName:"",profile:c},c.hasOwnProperty("upn")?b.userName=c.upn:c.hasOwnProperty("email")&&(b.userName=c.email)):this.warn("IdToken has invalid aud field")),b},AuthenticationContext.prototype._getHash=function(a){return a.indexOf("#/")>-1?a=a.substring(a.indexOf("#/")+2):a.indexOf("#")>-1&&(a=a.substring(1)),a},AuthenticationContext.prototype.isCallback=function(a){a=this._getHash(a);var b=this._deserialize(a);return b.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION)||b.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN)||b.hasOwnProperty(this.CONSTANTS.ID_TOKEN)},AuthenticationContext.prototype.getLoginError=function(){return this._getItem(this.CONSTANTS.STORAGE.LOGIN_ERROR)},AuthenticationContext.prototype.getRequestInfo=function(a){a=this._getHash(a);var b=this._deserialize(a),c={valid:!1,parameters:{},stateMatch:!1,stateResponse:"",requestType:this.REQUEST_TYPE.UNKNOWN};if(b&&(c.parameters=b,b.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION)||b.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN)||b.hasOwnProperty(this.CONSTANTS.ID_TOKEN))){c.valid=!0;var d="";if(!b.hasOwnProperty("state"))return this.warn("No state returned"),c;if(this.verbose("State: "+b.state),d=b.state,c.stateResponse=d,d===this._getItem(this.CONSTANTS.STORAGE.STATE_LOGIN))return c.requestType=this.REQUEST_TYPE.LOGIN,c.stateMatch=!0,c;if(!c.stateMatch&&window.parent&&window.parent.AuthenticationContext())for(var e=window.parent.AuthenticationContext()._renewStates,f=0;f-1&&b+1-1)return this.config.endpoints[b];if(!(a.indexOf("http://")>-1||a.indexOf("https://")>-1)){if(this.config&&this.config.anonymousEndpoints)for(var c=0;c-1)return null;return this.config.loginResource}return this._getHostFromUri(a)===this._getHostFromUri(this.config.redirectUri)?this.config.loginResource:null},AuthenticationContext.prototype._getHostFromUri=function(a){var b=String(a).replace(/^(https?:)\/\//,"");return b=b.split("/")[0]},AuthenticationContext.prototype.handleWindowCallback=function(){var a=window.location.hash;if(this.isCallback(a)){var b=this.getRequestInfo(a);this.info("Returned from redirect url"),this.saveTokenFromHash(b);var c=null;if(b.requestType===this.REQUEST_TYPE.RENEW_TOKEN&&window.parent?(this.verbose("Window is in iframe"),c=window.parent.callBackMappedToRenewStates[b.stateResponse],window.src=""):window&&window.oauth2Callback&&(this.verbose("Window is redirecting"),c=this.callback),window.location.hash="",window.location=this._getItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST),b.requestType===this.REQUEST_TYPE.RENEW_TOKEN)return void c(this._getItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION),b.parameters[this.CONSTANTS.ACCESS_TOKEN]||b.parameters[this.CONSTANTS.ID_TOKEN])}},AuthenticationContext.prototype._getNavigateUrl=function(a,b){var c="common";this.config.tenant&&(c=this.config.tenant),this.config.instance&&(this.instance=this.config.instance);var d=this.instance+c+"/oauth2/authorize"+this._serialize(a,this.config,b)+this._addLibMetadata();return this.info("Navigate url:"+d),d},AuthenticationContext.prototype._extractIdToken=function(a){var b=this._decodeJwt(a);if(!b)return null;try{var c=b.JWSPayload,d=this._base64DecodeStringUrlSafe(c);return d?JSON.parse(d):(this.info("The returned id_token could not be base64 url safe decoded."),null)}catch(e){this.error("The returned id_token could not be decoded",e)}return null},AuthenticationContext.prototype._extractUserName=function(a){try{var b=this._extractIdToken(a);if(b){if(b.hasOwnProperty("upn"))return b.upn;if(b.hasOwnProperty("email"))return b.email}}catch(c){this.error("The returned id_token could not be decoded",c)}return null},AuthenticationContext.prototype._base64DecodeStringUrlSafe=function(a){return a=a.replace(/-/g,"+").replace(/_/g,"/"),window.atob?decodeURIComponent(escape(window.atob(a))):decodeURIComponent(escape(this._decode(a)))},AuthenticationContext.prototype._decode=function(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";a=String(a).replace(/=+$/,"");var c=a.length;if(c%4===1)throw new Error("The token to be decoded is not correctly encoded.");for(var d,e,f,g,h,i,j,k,l="",m=0;c>m;m+=4){if(d=b.indexOf(a.charAt(m)),e=b.indexOf(a.charAt(m+1)),f=b.indexOf(a.charAt(m+2)),g=b.indexOf(a.charAt(m+3)),m+2===c-1){h=d<<18|e<<12|f<<6,i=h>>16&255,j=h>>8&255,l+=String.fromCharCode(i,j);break}if(m+1===c-1){h=d<<18|e<<12,i=h>>16&255,l+=String.fromCharCode(i);break}h=d<<18|e<<12|f<<6|g,i=h>>16&255,j=h>>8&255,k=255&h,l+=String.fromCharCode(i,j,k)}return l},AuthenticationContext.prototype._decodeJwt=function(a){if(this._isEmpty(a))return null;var b=/^([^\.\s]*)\.([^\.\s]+)\.([^\.\s]*)$/,c=b.exec(a);if(!c||c.length<4)return this.warn("The returned id_token is not parseable."),null;var d={header:c[1],JWSPayload:c[2],JWSSig:c[3]};return d},AuthenticationContext.prototype._convertUrlSafeToRegularBase64EncodedString=function(a){return a.replace("-","+").replace("_","/")},AuthenticationContext.prototype._serialize=function(a,b,c){var d=[];return null!==b&&(d.push("?response_type="+a),d.push("client_id="+encodeURIComponent(b.clientId)),c&&d.push("resource="+encodeURIComponent(c)),d.push("redirect_uri="+encodeURIComponent(b.redirectUri)),d.push("state="+encodeURIComponent(b.state)),b.hasOwnProperty("slice")&&d.push("slice="+encodeURIComponent(b.slice)),b.hasOwnProperty("extraQueryParameter")&&d.push(b.extraQueryParameter),b.correlationId&&d.push("client-request-id="+encodeURIComponent(b.correlationId))),d.join("&")},AuthenticationContext.prototype._deserialize=function(a){var b,c=/\+/g,d=/([^&=]+)=?([^&]*)/g,e=function(a){return decodeURIComponent(a.replace(c," "))},f={};for(b=d.exec(a);b;)f[e(b[1])]=e(b[2]),b=d.exec(a);return f},AuthenticationContext.prototype._guid=function(){for(var a="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx",b="0123456789abcdef",c=0,d="",e=0;36>e;e++)"-"!==a[e]&&"4"!==a[e]&&(c=16*Math.random()|0),"x"===a[e]?d+=b[c]:"y"===a[e]?(c&=3,c|=8,d+=b[c]):d+=a[e];return d},AuthenticationContext.prototype._expiresIn=function(a){return this._now()+parseInt(a,10)},AuthenticationContext.prototype._now=function(){return Math.round((new Date).getTime()/1e3)},AuthenticationContext.prototype._addAdalFrame=function(a){if("undefined"!=typeof a){this.info("Add adal frame to document:"+a);var b=document.getElementById(a);if(!b){if(document.createElement&&document.documentElement&&(window.opera||-1===window.navigator.userAgent.indexOf("MSIE 5.0"))){var c=document.createElement("iframe");c.setAttribute("id",a),c.style.visibility="hidden",c.style.position="absolute",c.style.width=c.style.height=c.borderWidth="0px",b=document.getElementsByTagName("body")[0].appendChild(c)}else document.body&&document.body.insertAdjacentHTML&&document.body.insertAdjacentHTML("beforeEnd",'');window.frames&&window.frames[a]&&(b=window.frames[a])}return b}},AuthenticationContext.prototype._saveItem=function(a,b){return this.config&&this.config.cacheLocation&&"localStorage"===this.config.cacheLocation?this._supportsLocalStorage()?(localStorage.setItem(a,b),!0):(this.info("Local storage is not supported"),!1):this._supportsSessionStorage()?(sessionStorage.setItem(a,b),!0):(this.info("Session storage is not supported"),!1)},AuthenticationContext.prototype._getItem=function(a){return this.config&&this.config.cacheLocation&&"localStorage"===this.config.cacheLocation?this._supportsLocalStorage()?localStorage.getItem(a):(this.info("Local storage is not supported"),null):this._supportsSessionStorage()?sessionStorage.getItem(a):(this.info("Session storage is not supported"),null)},AuthenticationContext.prototype._supportsLocalStorage=function(){try{return"localStorage"in window&&window.localStorage}catch(a){return!1}},AuthenticationContext.prototype._supportsSessionStorage=function(){try{return"sessionStorage"in window&&window.sessionStorage}catch(a){return!1}},AuthenticationContext.prototype._cloneConfig=function(a){if(null===a||"object"!=typeof a)return a;var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b},AuthenticationContext.prototype._addLibMetadata=function(){return"&x-client-SKU=Js&x-client-Ver="+this._libVersion()},AuthenticationContext.prototype.log=function(a,b,c){if(a<=Logging.level){var d=this.config.correlationId,e=(new Date).toUTCString(),f=e+":"+d+"-"+this._libVersion()+"-"+this.CONSTANTS.LEVEL_STRING_MAP[a]+" "+b;c&&(f+="\nstack:\n"+c.stack),Logging.log(f)}},AuthenticationContext.prototype.error=function(a,b){this.log(this.CONSTANTS.LOGGING_LEVEL.ERROR,a,b)},AuthenticationContext.prototype.warn=function(a){this.log(this.CONSTANTS.LOGGING_LEVEL.WARN,a,null)},AuthenticationContext.prototype.info=function(a){this.log(this.CONSTANTS.LOGGING_LEVEL.INFO,a,null)},AuthenticationContext.prototype.verbose=function(a){this.log(this.CONSTANTS.LOGGING_LEVEL.VERBOSE,a,null)},AuthenticationContext.prototype._libVersion=function(){return"1.0.10"};
\ No newline at end of file
diff --git a/lib/adal-angular.js b/lib/adal-angular.js
index 565da7e6..1b72a46f 100644
--- a/lib/adal-angular.js
+++ b/lib/adal-angular.js
@@ -1,5 +1,5 @@
//----------------------------------------------------------------------
-// AdalJS v1.0.9
+// AdalJS v1.0.10
// @preserve Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
// Apache License 2.0
@@ -89,7 +89,6 @@ if (typeof module !== 'undefined' && module.exports) {
}
if (requestInfo.requestType !== _adal.REQUEST_TYPE.LOGIN) {
- _adal._renewActive = false;
_adal.callback = $window.parent.AuthenticationContext().callback;
if (requestInfo.requestType === _adal.REQUEST_TYPE.RENEW_TOKEN) {
_adal.callback = $window.parent.callBackMappedToRenewStates[requestInfo.stateResponse];
@@ -108,6 +107,10 @@ if (typeof module !== 'undefined' && module.exports) {
} else if (requestInfo.parameters['id_token']) {
_adal.callback(_adal._getItem(_adal.CONSTANTS.STORAGE.ERROR_DESCRIPTION), requestInfo.parameters['id_token']);
return;
+ } else if (requestInfo.parameters['error']) {
+ _adal.callback(_adal._getItem(_adal.CONSTANTS.STORAGE.ERROR_DESCRIPTION), null);
+ _adal._renewFailed = true;
+ return;
}
}
} else {
@@ -147,10 +150,11 @@ if (typeof module !== 'undefined' && module.exports) {
// No callback. App resumes after closing or moving to new page.
// Check token and username
updateDataFromCache(_adal.config.loginResource);
- if (!_adal._renewActive && !_oauthData.isAuthenticated && _oauthData.userName) {
+ if (!_oauthData.isAuthenticated && _oauthData.userName && !_adal._renewActive && !_adal._renewFailed) {
// Idtoken is expired or not present
_adal._renewActive = true;
_adal.acquireToken(_adal.config.loginResource, function (error, tokenOut) {
+ _adal._renewActive = false;
if (error) {
$rootScope.$broadcast('adal:loginFailure', 'auto renew failure');
} else {
@@ -185,29 +189,54 @@ if (typeof module !== 'undefined' && module.exports) {
return global.requireADLogin ? route.requireADLogin !== false : !!route.requireADLogin;
}
+ function isAnonymousEndpoint(url) {
+ if (_adal.config && _adal.config.anonymousEndpoints) {
+ for (var i = 0; i < _adal.config.anonymousEndpoints.length; i++) {
+ if (url.indexOf(_adal.config.anonymousEndpoints[i]) > -1) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
var routeChangeHandler = function (e, nextRoute) {
- if (nextRoute && nextRoute.$$route && isADLoginRequired(nextRoute.$$route, _adal.config)) {
- if (!_oauthData.isAuthenticated && !_adal._renewActive) {
- _adal.info('Route change event for:' + $location.$$url);
- loginHandler();
+ if (nextRoute && nextRoute.$$route) {
+ if (isADLoginRequired(nextRoute.$$route, _adal.config)) {
+ if (!_oauthData.isAuthenticated && !_adal._renewActive) {
+ _adal.info('Route change event for:' + $location.$$url);
+ loginHandler();
+ }
+ }
+ else {
+ if (nextRoute.$$route.templateUrl && !isAnonymousEndpoint(nextRoute.$$route.templateUrl)) {
+ _adal.config.anonymousEndpoints.push(nextRoute.$$route.templateUrl);
+ }
}
}
};
var stateChangeHandler = function (e, toState, toParams, fromState, fromParams) {
- if (toState && isADLoginRequired(toState, _adal.config)) {
- if (!_oauthData.isAuthenticated && !_adal._renewActive) {
- // $location.$$url is set as the page we are coming from
- // Update it so we can store the actual location we want to
- // redirect to upon returning
- $location.$$url = toState.url;
-
- // Parameters are not stored in the url on stateChange so
- // we store them
- _adal._saveItem(_adal.CONSTANTS.STORAGE.START_PAGE_PARAMS, JSON.stringify(toParams));
-
- _adal.info('State change event for:' + $location.$$url);
- loginHandler();
+ if (toState) {
+ if (isADLoginRequired(toState, _adal.config)) {
+ if (!_oauthData.isAuthenticated && !_adal._renewActive) {
+ // $location.$$url is set as the page we are coming from
+ // Update it so we can store the actual location we want to
+ // redirect to upon returning
+ $location.$$url = toState.url;
+
+ // Parameters are not stored in the url on stateChange so
+ // we store them
+ _adal._saveItem(_adal.CONSTANTS.STORAGE.START_PAGE_PARAMS, JSON.stringify(toParams));
+
+ _adal.info('State change event for:' + $location.$$url);
+ loginHandler();
+ }
+ }
+ else {
+ if (toState.templateUrl && !isAnonymousEndpoint(toState.templateUrl)) {
+ _adal.config.anonymousEndpoints.push(toState.templateUrl);
+ }
}
}
};
@@ -300,6 +329,7 @@ if (typeof module !== 'undefined' && module.exports) {
config.headers = config.headers || {};
var resource = authService.getResourceForEndpoint(config.url);
+ authService.verbose('Url: ' + config.url + ' maps to resource: ' + resource);
if (resource === null) {
return config;
}
@@ -316,7 +346,6 @@ if (typeof module !== 'undefined' && module.exports) {
authService.info('login already start.');
return $q.reject('login in progress, cancelling the request');
} else {
- // external endpoints
// delayed request to return after iframe completes
var delayedRequest = $q.defer();
authService.acquireToken(resource).then(function (token) {
diff --git a/lib/adal.js b/lib/adal.js
index d02d88f0..1051ce1b 100644
--- a/lib/adal.js
+++ b/lib/adal.js
@@ -1,5 +1,5 @@
-//----------------------------------------------------------------------
-// AdalJS v1.0.9
+//----------------------------------------------------------------------
+// AdalJS v1.0.10
// @preserve Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
// Apache License 2.0
@@ -174,6 +174,7 @@ AuthenticationContext.prototype.login = function () {
this._saveItem(this.CONSTANTS.STORAGE.ERROR, '');
this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, '');
+
var urlNavigate = this._getNavigateUrl('id_token', null) + '&nonce=' + encodeURIComponent(this._idTokenNonce);
this.frameCallInProgress = false;
this._loginInProgress = true;
@@ -677,6 +678,7 @@ AuthenticationContext.prototype.saveTokenFromHash = function (requestInfo) {
if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN)) {
this.info('Fragment has access token');
resource = this._getResourceFromState(requestInfo.stateResponse);
+
if (!this._hasResource(resource)) {
keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS) || '';
this._saveItem(this.CONSTANTS.STORAGE.TOKEN_KEYS, keys + resource + this.CONSTANTS.RESOURCE_DELIMETER);
@@ -738,9 +740,18 @@ AuthenticationContext.prototype.getResourceForEndpoint = function (endpoint) {
return this.config.loginResource;
}
}
- // in angular level, the url for $http interceptor call could be relative url,
- // if it's relative call, we'll treat it as app backend call.
+ // in angular level, the url for $http interceptor call could be relative url,
+ // if it's relative call, we'll treat it as app backend call.
else {
+ // if user specified list of anonymous endpoints, no need to send token to these endpoints, return null.
+ if (this.config && this.config.anonymousEndpoints) {
+ for (var i = 0; i < this.config.anonymousEndpoints.length; i++) {
+ if (endpoint.indexOf(this.config.anonymousEndpoints[i]) > -1) {
+ return null;
+ }
+ }
+ }
+ // all other app's backend calls are secured.
return this.config.loginResource;
}
@@ -1173,5 +1184,5 @@ AuthenticationContext.prototype.verbose = function (message) {
};
AuthenticationContext.prototype._libVersion = function () {
- return '1.0.9';
-};
\ No newline at end of file
+ return '1.0.10';
+};
diff --git a/package.json b/package.json
index 86bdd03f..1ed39013 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
"type": "git",
"url": "https://github.com/AzureAD/azure-activedirectory-library-for-js.git"
},
- "version": "1.0.9",
+ "version": "1.0.10",
"description": "Windows Azure Active Directory Client Library for js",
"keywords": [
"implicit",
diff --git a/tests/angularModuleSpec.js b/tests/angularModuleSpec.js
index 769df3ee..b7e3c11b 100644
--- a/tests/angularModuleSpec.js
+++ b/tests/angularModuleSpec.js
@@ -224,4 +224,19 @@ describe('TaskCtl', function () {
rootScope.$apply();
expect(rootScope.$broadcast).toHaveBeenCalled();
});
+
+ it('tests callback is called when response contains error', function () {
+ window.parent.AuthenticationContext = function () {
+ return {
+ callback: function () { },
+ _renewStates: [ '4343' ]
+ };
+ };
+ window.parent.callBackMappedToRenewStates = {};
+ window.parent.callBackMappedToRenewStates['4343'] = function (error, token) {
+ expect(error).toBe('renewfailed');
+ };
+ window.location.hash = 'error=sample&error_description=renewfailed&state=4343';
+ rootScope.$apply();
+ });
});
diff --git a/tests/unit/spec/AdalSpec.js b/tests/unit/spec/AdalSpec.js
index 0a5efa7d..92029eb0 100644
--- a/tests/unit/spec/AdalSpec.js
+++ b/tests/unit/spec/AdalSpec.js
@@ -124,6 +124,14 @@ describe('Adal', function () {
expect(adal.getResourceForEndpoint('b')).toBe('default resource');
});
+ it('gets null resource for annonymous endpoints', function () {
+ adal.config.anonymousEndpoints = ['app/views'];
+ expect(adal.getResourceForEndpoint('app/views')).toBe(null);
+ expect(adal.getResourceForEndpoint('app/views/abc')).toBe(null);
+ expect(adal.getResourceForEndpoint('default/app/views/abc')).toBe(null);
+ expect(adal.getResourceForEndpoint('app/home')).toBe('default resource');
+ });
+
it('says token expired', function () {
adal.config.expireOffsetSeconds = SECONDS_TO_EXPIRE - 100;
expect(adal.getCachedToken(RESOURCE1)).toEqual('access_token_in_cache' + RESOURCE1);