我正在开发一个应用程序,其中包括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 0
或Azure AD
作为值。
app.value('loginOption', {value: null});
loginOption.value
在用户选择loginOption时被填充。
对于Auth 0
,我编辑了文件auth0-angular.js
。我在authUtilsProvider
的this.$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
Auth0
和Azure 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;
}
我不确定这是否是我问题的解决方案,但这对我来说是有效的。请纠正我,如果我错了在任何点,而回答。由于