Adal.js没有获得外部api端点资源的令牌

前端之家收集整理的这篇文章主要介绍了Adal.js没有获得外部api端点资源的令牌前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用从外部Web API站点(不同域)获取数据的Angular SPA(单页面应用程序)网站来尝试adal.js.通过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 Azure AD应用程序的客户端ID,另一个用于外部api.只有SPA令牌有一个值.
>如果我不注入$httpProvider到adal.js,那么调用去外部API,我得到一个401回报.
>如果我手动将SPA令牌添加到http头(授权:承载“令牌值”),我得到一个401返回.

我的理论是,adal.js无法为端点检索令牌(可能是因为我在SPA中配置了错误的东西),并且它阻止了端点的流量,因为它无法获取必需的令牌. SPA令牌不能用于API,因为它不包含所需的权限.为什么adal.js没有得到端点的令牌,我该如何解决

附加信息:

>客户端Azure AD应用程序配置为在API中使用委托权限,并在应用程序清单中使用oauth2AllowImplicitFlow = true.
> API Azure AD应用程序配置为模拟,而oauth2AllowImplicitFlow = true(不要以为这是必需的,但尝试过).它是多租户.
> API被配置为允许所有CORS源代码,并且在使用模拟(混合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
                    );
        }]);
})();

呼叫端点的角码:

$scope.getItems = function () {
            $http.get("https://localhost/Api/Items")
                .then(function (response) {                        
                    $scope.items = response.Items;
                });

解决方法

我不知道我们的设置是否完全一样,但我认为它是可比的.

我有一个Angular SPA,通过Azure API管理(APIM)使用外部Web API.我的代码可能不是最佳实践,但它对我来说至今为止:)

SPA Azure AD应用程序具有访问外部API Azure AD应用程序的授权.

SPA(基于Adal TodoList SPA sample)

app.js

adalProvider.init(
    {
        instance: 'https://login.microsoftonline.com/',tenant: 'mysecrettenant.onmicrosoft.com',clientId: '********-****-****-****-**********',//ClientId of the Azure AD app for my SPA app            
        extraQueryParameter: 'nux=1',cacheLocation: 'localStorage',// enable this for IE,as sessionStorage does not work for localhost.
    },$httpProvider
    );

来自todoListSvc.js的代码

getWhoAmIBackend: function () {
        return $http.get('/api/Employee/GetWhoAmIBackend');
    },

来自EmployeeController的代码

public string GetWhoAmIBackend()
    {
        try
        {
            AuthenticationResult result = GetAuthenticated();

            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",result.AccessToken);

            var request = new HttpRequestMessage()
            {
                RequestUri = new Uri(string.Format("{0}","https://api.mydomain.com/secretapi/api/Employees/GetWhoAmI")),Method = HttpMethod.Get,//This is the URL to my APIM endpoint,but you should be able to use a direct link to your external API

            };
            request.Headers.Add("Ocp-Apim-Trace","true"); //Not needed if you don't use APIM
            request.Headers.Add("Ocp-Apim-Subscription-Key","******mysecret subscriptionkey****"); //Not needed if you don't use APIM

            var response = client.SendAsync(request).Result;
            if (response.IsSuccessStatusCode)
            {
                var res = response.Content.ReadAsStringAsync().Result;
                return res;
            }
            return "No dice :(";
        }
        catch (Exception e)
        {
            if (e.InnerException != null)
                throw e.InnerException;
            throw e;
        }
    }

        private static AuthenticationResult GetAuthenticated()
    {
        BootstrapContext bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as BootstrapContext;
        var token = bootstrapContext.Token;

        Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authContext =
            new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("https://login.microsoftonline.com/mysecrettenant.onmicrosoft.com");

        //The Client here is the SPA in Azure AD. The first param is the ClientId and the second is a key created in the Azure Portal for the AD App
        ClientCredential credential = new ClientCredential("clientid****-****","secretkey ********-****");

        //Get username from Claims
        string userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;

        //Creating UserAssertion used for the "On-Behalf-Of" flow
        UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token,"urn:ietf:params:oauth:grant-type:jwt-bearer",userName);

        //Getting the token to talk to the external API
        var result = authContext.AcquireToken("https://mysecrettenant.onmicrosoft.com/backendAPI",credential,userAssertion);
        return result;
    }

现在,在我的后端外部API中,我的Startup.Auth.cs如下所示:

外部API
Startup.Auth.cs

public void ConfigureAuth(IAppBuilder app)
    {
        app.UseWindowsAzureActiveDirectoryBearerAuthentication(
            new WindowsAzureActiveDirectoryBearerAuthenticationOptions
            {
                Tenant = ConfigurationManager.AppSettings["ida:Tenant"],TokenValidationParameters = new TokenValidationParameters
                {
                    ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],SaveSigninToken = true
                },AuthenticationType = "OAuth2Bearer"
            });
    }

如果这有帮助,或者我可以进一步的帮助,请通知我.

原文链接:https://www.f2er.com/js/155147.html

猜你在找的JavaScript相关文章