Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JQuery使用AAD访问.Net Web Api抛出401无效\u令牌/颁发者无效_Javascript_Jquery_Authentication_Asp.net Web Api_Azure Active Directory - Fatal编程技术网

Javascript JQuery使用AAD访问.Net Web Api抛出401无效\u令牌/颁发者无效

Javascript JQuery使用AAD访问.Net Web Api抛出401无效\u令牌/颁发者无效,javascript,jquery,authentication,asp.net-web-api,azure-active-directory,Javascript,Jquery,Authentication,Asp.net Web Api,Azure Active Directory,我正试图在Azure中创建一个简单的.Net核心Web Api,以使用JQuery测试身份验证。我设法解决了CORS问题,但在尝试使用承载令牌时,我不断收到401“发卡机构无效”错误。我能够使用Postman和secret测试Web Api,但在使用JQuery和AAD时无法测试。我从一个单独工作的示例中提取了一些演示SPA代码,但当我将客户机和Web Api放在单独的项目中时,这些代码就不起作用了。我认为可能需要使用Web Api的客户端ID来获取令牌,但这似乎没有任何效果。控制器再简单不过了

我正试图在Azure中创建一个简单的.Net核心Web Api,以使用JQuery测试身份验证。我设法解决了CORS问题,但在尝试使用承载令牌时,我不断收到401“发卡机构无效”错误。我能够使用Postman和secret测试Web Api,但在使用JQuery和AAD时无法测试。我从一个单独工作的示例中提取了一些演示SPA代码,但当我将客户机和Web Api放在单独的项目中时,这些代码就不起作用了。我认为可能需要使用Web Api的客户端ID来获取令牌,但这似乎没有任何效果。控制器再简单不过了

namespace test_core_web_api_spa.Controllers
{
    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/values/5
        [HttpGet("{id}")]
        public ActionResult<string> Get(int id)
        {
            return "value";
        }

        // POST api/values
        [HttpPost]
        public void Post([FromBody] string value)
        {
            // For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
        }

        // PUT api/values/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody] string value)
        {
            // For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
        }

        // DELETE api/values/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
            // For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
        }
    }
}
HTML页面是使用AAD从SPA演示中复制的

<!DOCTYPE html>
<html>
<head>
    <title>Test API Call</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
    <link rel="stylesheet" href="/css/app.css">
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed"
                        data-toggle="collapse"
                        data-target=".navbar-collapse">

                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/#Home">test api call</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/#Home">Home</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li class="app-user navbar-text"></li>
                    <li><a href="javascript:;" class="app-logout">Logout</a></li>
                    <li><a href="javascript:;" class="app-login">Login</a></li>
                </ul>
            </div>
        </div>
    </div>

    <div id="divHome" class="container-fluid">
        <div class="jumbotron">
            <h5 id="WelcomeMessage"></h5>
            <div class="text-hide">Surname: <span id="userSurName"></span><span id="userEmail"></span></div>
            <h2>test page</h2>
        </div>

        <div>
            <br />
            <a href="javascript:;" class="btnCallApiTest">Call Api</a>
            <br />
            <p class="view-loading">Loading...</p>
            <div class="app-error"></div>
            <br />
            <span id="data-container"></span>
        </div>
        <br />
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="https://alcdn.msauth.net/lib/1.1.3/js/msal.js" integrity="sha384-m/3NDUcz4krpIIiHgpeO0O8uxSghb+lfBTngquAo2Zuy2fEF+YgFeP08PWFo5FiJ" crossorigin="anonymous"></script>
    <script src="js/rest_api.js"></script>

</body>
</html>
登录确实与AAD一起工作,并收回我的电子邮件地址。我确实看到创建了一个令牌并将其传递给Web Api。但随后它给出了“发卡机构无效”401错误。在发出令牌请求时,我是Web Api的客户端Id,因此我不确定还能更改什么

根据注释,我尝试将作用域传递给
loginPopup
调用

    $signInButton.click(function () {
        clientApplication.loginPopup(requestObj).then(onSignin);
    });
但是,唯一有效的值给出了相同的结果:

var requestObj = ["web-api-client-id"];
我尝试了运行本地web服务的URL,包括使用
https://localhost:44399/.default
但在获取带有消息(如
名为https://localhost:44399 在租户中找不到
。如果问题是此调用中的作用域设置,那么我不确定在调试时使用什么值使其在本地工作。作为补充说明,我发现其他Github示例使用的格式为

var requestObj = {scopes: ["api://clientid/access_as_user"]};
但是如果说
API不接受非数组作用域,这些函数将无法执行。我可能会在另一个帖子里问这个问题

11月13日更新 我从MSAL的0.2.3切换到1.1.3,然后更新逻辑以反映不同版本中所做的更改

我还确认客户端应用程序具有web API的API权限。我在web api中添加了一个称为“用户模拟”的新作用域。在我的租户中,现有的“api访问”被锁定为管理员控制

尝试使用“api/”表单时,找不到资源。以下是我尝试的值,它们都得到相同的错误。我认为这种格式是传统的


scopes: ["api://web-api-clientid"]
scopes: ["api://web-api-clientid/api-access"]
scopes: ["api://web-api-clientid/user_impersonation"]
scopes: ["api://web-api-clientid/.default"]
ServerError: AADSTS500011: The resource principal named api://web-api-clientid was not found in the tenant named my-tenant-id. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
尝试这些作用域时,错误为“无效”

scopes: ["https://myPortal.onmicrosoft.com/test_core_web_api_spa/user_impersonation"]
scopes: ["https://myPortal.onmicrosoft.com/test_core_web_api_spa/.default"]
401 www-authenticate: Bearer error="invalid_token", error_description="The audience is invalid" 
"aud": "https://myPortal.onmicrosoft.com/test_core_web_api_spa"
尝试这些作用域时,错误消息会使我的客户端应用程序正确,但我的门户上似乎不存在我的web api应用程序

scopes: ["https://myPortal.onmicrosoft.com/test_core_web_api_spa"]
scopes: ["https://myPortal.onmicrosoft.com/test_core_web_api_spa","user_impersonation"]
ServerError: AADSTS650053: The application 'demoapp-frontend' asked for scope 'test_core_web_api_spa' that doesn't exist on the resource 'myportal_guid'. 

很抱歉给你带来这么多的困惑,但是我已经尝试了所有的方法,代码变得越来越混乱。我几乎到了需要重新开始的地步

如下所示修改您的代码

window.config = {
        clientID: 'clientidof_web_client'
    };
    var scope = ["api://{clientidof_web_api}/.default"];
你可以用它来检查代币。aud的值应为
api://client_id_of_web_api

更新:

您是否已将api添加到您的客户端应用程序权限中


问题在于Web API的配置数据。当他们说
ClientId
时,他们真正想要的是“exposeanapi”选项下的值,其中显示“applicationiduri”。我在那里输入的是Web Api应用程序注册的guid。下面是它的外观

  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "myportal.onmicrosoft.com",
    "TenantId": "mytenant-guid",
    "ClientId": "https://myportal.onmicrosoft.com/test_core_web_api_spa"
  },

范围不正确。您应该使用类似于
api://{webapi客户端id}/.default的东西。此外,您可以使用检查令牌。作用域基于提供的示例,该示例显示作用域应该是在Azure中注册的clientID。文件具体是。请尝试在此处更改作用域
clientApplication.acquireTokenSilent(作用域)
您可以通过解码来检查令牌。aud的值应为
api://client_id
。您不应仅将客户端id用作作用域,因为这样会获得id令牌。您需要的是一个访问令牌。这会引发一个错误。看来AAD正在寻找客户ID。AADSTS700016:在目录“tenantid”中找不到标识符为“api://{clientid}/.default”的应用程序。如果应用程序尚未由租户的管理员安装或租户中的任何用户同意,则可能发生这种情况。您可能向错误的租户发送了身份验证请求。在我的原始代码中使用JWT会显示aud值,以匹配Azure中Web Api应用程序的客户端ID。@pretzelb请查看更新答案中的屏幕截图。该Api格式似乎不起作用。我尝试了所有的组合,得到了相同的错误<代码>作用域:[”api://web-api-clientid“]作用域:[”api://web-api-clientid/api-access“]作用域:[”api://web-api-clientid/user_impersonation“]作用域:[”api://web-api-clientid/.default"]ServerError:AADSTS500011:名为api://web-api-clientid 在名为my-tenant-id的租户中找不到。如果租户的管理员未安装应用程序或租户中的任何用户未同意安装应用程序,则可能发生这种情况。
window.config = {
        clientID: 'clientidof_web_client'
    };
    var scope = ["api://{clientidof_web_api}/.default"];
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "myportal.onmicrosoft.com",
    "TenantId": "mytenant-guid",
    "ClientId": "https://myportal.onmicrosoft.com/test_core_web_api_spa"
  },