我正在使用 adal.js 与一个 Angular SPA(单页应用程序)网站尝试获取来自外部 Web API 站点(不同域)的数据。使用 adal.js 进行 SPA 认证很容易,但当需要承载令牌时,让其与 API 通信完全不起作用。除了无数博客之外,我还使用了 https://github.com/AzureAD/azure-activedirectory-library-for-js 作为模板。
问题在于,当我在初始化 adal.js 时设置端点时,它似乎会将所有外部端点流量重定向到 Microsoft 的登录服务。
观察结果:
- Adal.js 会话存储包含两个 adal.access.token.key 条目。一个用于 SPA Azure AD 应用程序的客户端 ID,另一个用于外部 api。只有 SPA 令牌有值。
- 如果我不将 $httpProvider 注入到 adal.js 中,则调用会发送到外部 API,并且我会得到 401 响应。
- 如果我手动将 SPA 令牌添加到 http 标头中(授权:bearer 'token value'),则会得到 401 响应。
我的理论是,adal.js 无法检索端点的令牌(可能是因为我在 SPA 中配置了错误的内容),并且它停止流量到端点,因为无法获取所需的令牌。SPA 令牌不能用于 API,因为它不包含所需的权限。 为什么 adal.js 无法为端点获取令牌,我该如何解决?
附加信息:
- 客户端 Azure AD 应用程序已配置为针对 API 使用委派权限,并在应用程序清单中启用 oauth2AllowImplicitFlow = true。
- API Azure AD 应用程序已配置为模拟和 oauth2AllowImplicitFlow = true(不认为这是必需的,但尝试了一下)。它是多租户的。
- API 已配置为允许所有 CORS 来源,并且当使用模拟 (hybrid MVC (Adal.net) + Angular) 的另一个 Web 应用程序时,它可以正常工作。
会话存储:
key (for the SPA application): adal.access.token.keyxxxxx-b7ab-4d1c-8cc8-xxx value: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1u...
key (for API application): adal.access.token.keyxxxxx-bae6-4760-b434-xxx
value:
app.js(Angular和adal配置文件)
(function () {
'use strict';
var app = angular.module('app', [
// Angular modules
'ngRoute',
// Custom modules
// 3rd Party Modules
'AdalAngular'
]);
app.config(['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider
// route for the home page
.when('/home', {
templateUrl: 'App/Features/Test1/home.html',
controller: 'home'
})
// route for the about page
.when('/about', {
templateUrl: 'App/Features/Test2/about.html',
controller: 'about',
requireADLogin: true
})
.otherwise({
redirectTo: '/home'
})
//$locationProvider.html5Mode(true).hashPrefix('!');
}]);
app.config(['$httpProvider', 'adalAuthenticationServiceProvider',
function ($httpProvider, adalAuthenticationServiceProvider) {
// endpoint to resource mapping(optional)
var endpoints = {
"https://localhost/Api/": "xxx-bae6-4760-b434-xxx",
};
adalAuthenticationServiceProvider.init(
{
// Config to specify endpoints and similar for your app
clientId: "xxx-b7ab-4d1c-8cc8-xxx", // Required
//localLoginUrl: "/login", // optional
//redirectUri : "your site", optional
extraQueryParameter: 'domain_hint=mydomain.com',
endpoints: endpoints // If you need to send CORS api requests.
},
$httpProvider // pass http provider to inject request interceptor to attach tokens
);
}]);
})();
调用端点的Angular代码:
$scope.getItems = function () {
$http.get("https://localhost/Api/Items")
.then(function (response) {
$scope.items = response.Items;
});