首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Adal.js不为外部api端点资源获取令牌。

Adal.js不为外部api端点资源获取令牌。
EN

Stack Overflow用户
提问于 2015-09-02 11:47:42
回答 4查看 13.1K关注 0票数 16

我正在试用adal.js的角度SPA (单页应用程序)网站,从外部的web网站(不同的领域)数据。adal.js很容易对SPA进行身份验证,但是当需要承载令牌时,让它与API通信根本不起作用。除了无数的博客之外,我还使用了https://github.com/AzureAD/azure-activedirectory-library-for-js作为模板。

问题是,当我在启动adal.js时设置端点时,adal.js似乎将所有传出端点流量重定向到microsofts登录服务。

意见:

  • Adal.js会话存储包含两个adal.access.token.key条目。一个用于SPA应用程序的客户端ID,另一个用于外部api。只有SPA令牌有一个值。
  • 如果我不将$httpProvider注入adal.js,那么调用到外部API并得到401作为回报。
  • 如果我手动将SPA令牌添加到http报头(授权:承载‘令牌值’),我将得到401作为回报。

我的理论是,adal.js无法为端点检索令牌(可能是因为我在SPA中配置了一些错误),并且由于它无法获得所需的令牌,所以它停止了对端点的通信。SPA令牌不能针对API使用,因为它不包含所需的权限。为什么adal.js没有为端点获取令牌,以及如何修复它?

其他信息:

  • 客户端Azure应用程序被配置为对API和oauth2AllowImplicitFlow = true在app清单中使用委托权限。
  • Azure应用程序被配置为模拟和oauth2AllowImplicitFlow = true (不要认为这是必需的,而是尝试过)。是多租户。
  • 该API被配置为允许所有CORS起源,并且当其他web应用使用模拟(混合MVC (Adal.net) +角)时,它正确工作。

会话存储:

代码语言:javascript
复制
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 (角和adal配置文件)

代码语言:javascript
复制
(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
                    );
        }]);
})();

调用端点的角码:

代码语言:javascript
复制
$scope.getItems = function () {
            $http.get("https://localhost/Api/Items")
                .then(function (response) {                        
                    $scope.items = response.Items;
                });
EN

回答 4

Stack Overflow用户

发布于 2017-06-29 21:15:26

好吧,我一直把头撞在墙上想办法解决这个问题。试图使我的ADAL.js SPA应用程序(sans角)成功地提出跨域XHR请求到我宝贵的CORS支持的Web。

所有像我这样的新手使用的这个示例应用程序都有这样的问题:它的特点是API和SPA都来自同一个域,并且只需要注册一个AD租户应用程序。这只会让事情变得混乱,当需要把东西分开分开的时候。

所以,开箱即用,这个样本有一个Startup.Auth.cs,它可以正常工作,就这个示例来说……

代码语言:javascript
复制
  public void ConfigureAuth(IAppBuilder app) {

        app.UseWindowsAzureActiveDirectoryBearerAuthentication(
            new WindowsAzureActiveDirectoryBearerAuthenticationOptions
            {
                Audience = ConfigurationManager.AppSettings["ida:Audience"],
                Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
            });
  }

但是,您需要修改上面的代码,删除Audience赋值,然后选择一个受众数组。没错:ValidAudiences ..。因此,对于与您的WebAPI通信的每个SPA客户端,您都希望将SPA注册的ClientID放在这个数组中.

它应该是这样的.

代码语言:javascript
复制
public void ConfigureAuth(IAppBuilder app)
{
    app.UseWindowsAzureActiveDirectoryBearerAuthentication(
        new WindowsAzureActiveDirectoryBearerAuthenticationOptions
        {
            Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
            TokenValidationParameters = new TokenValidationParameters
            {
                ValidAudiences = new [] { 
                 ConfigurationManager.AppSettings["ida:Audience"],//my swagger SPA needs this 1st one
                 "b2d89382-f4d9-42b6-978b-fabbc8890276",//SPA ClientID 1
                 "e5f9a1d8-0b4b-419c-b7d4-fc5df096d721" //SPA ClientID 2
                 },
                RoleClaimType = "roles" //Req'd only if you're doing RBAC 
                                        //i.e. web api manifest has "appRoles"
            }
        });
}

编辑

好的,基于@JonathanRupp的反馈,我能够反转我使用的Web解决方案,并且能够修改我的客户端JavaScript,如下所示,使一切正常工作。

代码语言:javascript
复制
    // Acquire Token for Backend
    authContext.acquireToken("https://mycorp.net/WebApi.MyCorp.RsrcID_01", function (error, token) {

        // Handle ADAL Error
        if (error || !token) {
            printErrorMessage('ADAL Error Occurred: ' + error);
            return;
        }

        // Get TodoList Data
        $.ajax({
            type: "GET",
            crossDomain: true,
            headers: {
                'Authorization': 'Bearer ' + token
            },
            url: "https://api.mycorp.net/odata/ToDoItems",
        }).done(function (data) {
            // For Each Todo Item Returned, do something
            var output = data.value.reduce(function (rows, todoItem, index, todos) {
                //omitted
            }, '');

            // Update the UI
            //omitted

        }).fail(function () {
            //do something with error
        }).always(function () {
            //final UI cleanup
        });
    });
票数 2
EN

Stack Overflow用户

发布于 2016-02-25 13:32:33

您需要让您的Web知道您的客户端应用程序。仅从客户端向API添加委托权限是不够的。

要让API客户端知道,请转到Azure管理门户,下载API的清单并将客户端应用程序的ClientID添加到"knownClientApplications“列表中。

要允许隐式流,还需要在清单中将"oauth2AllowImplicitFlow“设置为true。

将清单上载回API应用程序。

票数 1
EN

Stack Overflow用户

发布于 2016-12-29 05:04:47

ADAL.js在调用运行在不同域上的Azure保护API时,确实将access_token与id_token区别开来。最初,在登录期间,它只需使用id_token。此令牌有权访问同一域的资源。但是,在调用运行在不同域中的API时,adal拦截器会检查API是否配置在adal.init()中的端点中。

只有到那时,才会为请求的资源调用访问令牌。它还要求SPA在AAD中配置为访问API应用程序。

实现这一目标的关键是: 1.在adal.init()中添加端点

代码语言:javascript
复制
var endpoints = {

    // Map the location of a request to an API to a the identifier of the associated resource
    //"Enter the root location of your API app here, e.g. https://contosotogo.azurewebsites.net/":
    //    "Enter the App ID URI of your API app here, e.g. https://contoso.onmicrosoft.com/TestAPI",
    "https://api.powerbi.com": "https://analysis.windows.net/powerbi/api",
    "https://localhost:44300/": "https://testpowerbirm.onmicrosoft.com/PowerBICustomServiceAPIApp"
};

adalProvider.init(
    {
        instance: 'https://login.microsoftonline.com/',
        tenant: 'common',
        clientId: '2313d50b-7ce9-4c0e-a142-ce751a295175',
        extraQueryParameter: 'nux=1',
        endpoints: endpoints,
        requireADLogin: true,

        //cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.  
        // Also, token acquisition for the To Go API will fail in IE when running on localhost, due to IE security restrictions.
    },
    $httpProvider
    );
  1. 允许Azure AD中的SPA应用程序访问API应用程序:

有关详细信息,请参阅此链接:ADAL.js深潜

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32352325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档