身份验证 0 和 Azure AD 的 Angular 拦截器干扰彼此的身份验证过程



我正在开发一个应用程序,其中包括Auth 0和Azure AD用于不同域的用户身份验证。如。Auth0适用于gmail和outlook.com, Azure AD适用于其他域。我想把它们分开。为此,我显示一个选项页面,用户选择登录选项(Auth0或AzureAd)。

我正在使用Angularjs框架和. net

如果只使用一个登录选项,即Auth0或Azure AD, Auth0和Azure AD的登录过程都是顺利的。但当它们一起使用时,就会发出胡言乱语。问题开始于状态路由和从claimprincipal (. net)访问登录用户的电子邮件。一个(Auth0/AzureAd)似乎覆盖了claimprincipal。如。如果我在Azure AD中使用a@b.com登录和注销,我尝试通过Auth0使用电子邮件c@d.com再次登录, claimprincipal仍然返回Azure AD用户的电子邮件,即a@b而不是c@d。

我确信这是发生的,因为有两个拦截器拦截请求,每个一个。ProtectedResourceInterceptor: Azure AD

jwtInterceptor: Auth0

我试图创建一个服务提供商,它动态地尝试从$httpProvider推送或弹出拦截器,选择登录选项(Auth0/AzureAD)。

 app.config(['$provide', '$httpProvider', function ($provide, $httpProvider) {
    $provide.decorator('$interceptorManager', ['$delegate', '$injector', function ($delegate, $injector) {
        $delegate.addInterceptor = function (loginOptionValue) {                            
            if (loginOptionValue) {
                switch (loginOptionValue) {
                    case 'Auth 0':
                        var index = $httpProvider.interceptors.indexOf('ProtectedResourceInterceptor');
                        if (index != -1) $httpProvider.interceptors.splice(index, 1);
                        $httpProvider.interceptors.push('jwtInterceptor');
                        break;
                    case 'Azure Ad':
                        var index = $httpProvider.interceptors.indexOf('jwtInterceptor');
                        if (index != -1) $httpProvider.interceptors.splice(index, 1);
                        $httpProvider.interceptors.push('ProtectedResourceInterceptor');
                        break;
                }
            }
            console.log('Adding Interceptio: '+$httpProvider.interceptors.length);
        }
        $delegate.removeInterceptors = function (loginOptionValue) {
            var index = -1;
           //var index = $httpProvider.interceptors.indexOf('ProtectedResourceInterceptor');
           //if (index != -1) $httpProvider.interceptors.splice(index, 1);
           index = $httpProvider.interceptors.indexOf('jwtInterceptor');
           if (index != -1) $httpProvider.interceptors.splice(index, 1);
        }
        $delegate.printInterceptors = function () {
            for (var i = 0 ; i < $httpProvider.interceptors.length ; i++)
                console.log($httpProvider.interceptors[i]);
        }
        return $delegate;
    }]);
}]);

但是似乎对我不起作用。我应该如何实现不间断登录过程,同时部署Auth 0和Azure AD ?

放弃了从Auth0访问Azure Ad的想法。我回滚到前面的步骤,在那里我有两个选项(Auth0或Azure AD)之间进行选择。

对于任何正在寻找答案的人,好吧,我试着编辑拦截器。我不知道我是否应该编辑拦截器,但我做了一点,它为我工作。

就是这样。我创建了一个angular value,并将其命名为loginOption,在module creation的开始处具有value的属性。loginOption可以保存Auth 0Azure AD作为值。

app.value('loginOption', {value: null});

loginOption.value在用户选择loginOption时被填充。

对于Auth 0,我编辑了文件auth0-angular.js。我在authUtilsProviderthis.$get中注射loginOption,并调理$stateChangeStart

$rootScope.$on('$stateChangeStart', function (e, to) {
  if (!config.initialized) {
    return;
  }
  //prevent state change only when the state change is in the favor of Auth0 or login option is yet to be selected
  //now, it won't prevent state change when done by Azure AD
  if (to.data && to.data.requiresLogin && (!loginOption.value || loginOption.value === 'Auth 0')) {
    if (!auth.isAuthenticated && !auth.refreshTokenPromise) {
      e.preventDefault();
      $injector.get('$state').go(config.loginState);
    }
  }
});

对于Azure AD,我编辑了文件adal-angular.js。我在ProtectedResourceInterceptor中注入了loginOption,并调节了一些代码。

//to prevent adding token of Azure Ad into header of Auth 0 requests
if (tokenStored && (loginOption.value === loginOptions.AZURE_AD)) {
    authService.info('Token is available for this url ' + config.url);
    // check endpoint mapping if provided
    config.headers.Authorization = 'Bearer ' + tokenStored;
    return config;
}

if (loginOption.value === loginOptions.AZURE_AD) {
    // delayed request to return after iframe completes
    var delayedRequest = $q.defer();
    authService.acquireToken(resource).then(function (token) {
        authService.verbose('Token is available');
        config.headers.Authorization = 'Bearer ' + token;
        delayedRequest.resolve(config);
    }, function (err) {
        config.data = err;
        delayedRequest.reject(config);
    });
    return delayedRequest.promise;
}

不需要在后端做任何事情。一定要在Startup.cs

中为Auth0Azure Ad添加令牌验证器
//for Azure Ad
UseWindowsAzureActiveDirectoryBearerAuthentication 
//for Auth0
UseJwtBearerAuthentication 

最后但并非最不重要的是索赔。对于Auth0,可以从ClaimTypes.Email检索到电子邮件,对于Azure Ad,可以从ClaimTypes.Name检索到电子邮件。

public static Claim GetClaim(string claimType)
{
    return ClaimsPrincipal.Current.FindFirst(claimType);
}
public static string GetLoggedInUserEmail()
{
    //Email comes up for Auth0
    var claimEmail = GetClaim(ClaimTypes.Email);
    //if claimEmail comes out to be null from ClaimTypes.Email then try it out for ClaimTypes.Name
    if (claimEmail == null)
        //Name comes up for Azure AD
        claimEmail = GetClaim(ClaimTypes.Name);
    var email = (claimEmail == null ? string.Empty : claimEmail.Value); //gets the email of the user
    return email;
}

我不确定这是否是我问题的解决方案,但这对我来说是有效的。请纠正我,如果我错了在任何点,而回答。由于

相关内容

  • 没有找到相关文章

最新更新