从AngularJS / ADAL.js客户端访问WebApI时出现401未经授权的错误 [英] 401 Unauthorized errors when accessing WebApI from AngularJS/ADAL.js client

查看:230
本文介绍了从AngularJS / ADAL.js客户端访问WebApI时出现401未经授权的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有前端前端的自托管Web api应用程序,现在需要开始通过Azure Active Directory对用户进行身份验证。

I've got a self-hosted web api application with an angular front end, and I need to now start authenticating users via Azure Active Directory.

我'下载了SinglePageApp示例,并进行了设置并使其成功运行。
https://github.com/Azure-样本/ active-directory-angularjs-singlepageapp-dotnet-webapi

I've downloaded the SinglePageApp example and I've set this up and have it running successfully. https://github.com/Azure-Samples/active-directory-angularjs-singlepageapp-dotnet-webapi

在对自己的应用程序进行必要的更改后,我可以成功地将用户重定向到Azure登录屏幕,并使用adal.js / adal_angular.js取回userProfile。每当我调用API时,都会收到401个未经授权的错误,但是使用Fiddler,我可以看到在每次调用中HTTP头中都添加了承载令牌。

When applying the necessary changes to my own app, I can successfully redirect the user to the Azure login screen and get back the userProfile using adal.js/adal_angular.js. I'm getting 401 unauthorized errors whenever I call my API, however using Fiddler, I can see that the bearer token is added to the HTTP header in each call.

此处是我的AdalAngular设置:

Here is my AdalAngular setup:

.config(["$httpProvider", "adalAuthenticationServiceProvider", ($httpProvider, adalProvider) => {
            adalProvider.init(
            {
                instance: "https://login.microsoftonline.com/",
                tenant: "<snip>.onmicrosoft.com",
                clientId: "<snip>",
                extraQueryParameter: "nux=1",
                cacheLocation: "localStorage" // enable this for IE, as sessionStorage does not work for localhost.
            },
            $httpProvider);

这是我的startup.cs代码:

Here is my startup.cs code:

public void Configuration(IAppBuilder appBuilder)
    {

        ConfigureWebApi(appBuilder);
        ConfigureAuth(appBuilder);
        ConfigureFileSystem(appBuilder);
        appBuilder.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    }

private void ConfigureWebApi(IAppBuilder appBuilder)
    {
        // Configure Web API for self-host. 
        HttpConfiguration config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        appBuilder.UseWebApi(config);
    }

    private void ConfigureAuth(IAppBuilder app)
    {
        app.UseWindowsAzureActiveDirectoryBearerAuthentication(
            new WindowsAzureActiveDirectoryBearerAuthenticationOptions
            {
                Tenant = ConfigurationManager.AppSettings["ActiveDirectoryTenant"],
                Audience = ConfigurationManager.AppSettings["ActiveDirectoryApplicationId"]
            });
    }

    private void ConfigureFileSystem(IAppBuilder appBuilder)
    {

        //Set the Welcome page to test if Owin is hosted properly
        appBuilder.UseWelcomePage("/welcome.html");
        appBuilder.UseErrorPage(new Microsoft.Owin.Diagnostics.ErrorPageOptions() { ShowExceptionDetails = true });
        var physicalFileSystem = new PhysicalFileSystem(@".\wwwroot");
        if (ConfigurationManager.AppSettings.AllKeys.Contains("ContentPath"))
        {
            var path = ConfigurationManager.AppSettings["ContentPath"];
            physicalFileSystem = new PhysicalFileSystem(path);
        }
        FileServerOptions fileOptions = new FileServerOptions();

        fileOptions.EnableDefaultFiles = true;
        fileOptions.RequestPath = PathString.Empty;
        fileOptions.FileSystem = physicalFileSystem;
        fileOptions.DefaultFilesOptions.DefaultFileNames = new[] { "index.html" };
        fileOptions.StaticFileOptions.FileSystem = fileOptions.FileSystem = physicalFileSystem;
        fileOptions.StaticFileOptions.ServeUnknownFileTypes = true;
        appBuilder.UseFileServer(fileOptions);
    }

ActiveDirectoryTenant和ActiveDirectoryApplicationId在我的app.config中,并与其中配置的内容匹配

Where ActiveDirectoryTenant and ActiveDirectoryApplicationId are in my app.config and match what is configured in my angular adalProvider.init code exactly.

最后,我的ApiController看起来像这样:

Finally, my ApiController looks like this:

 [Authorize]
[RoutePrefix("api/connection")]
public class ServerConnectionController : ApiController
{
    [Route("all")]
    [HttpGet]
    public HttpResponseMessage GetAllConnections()
    {
        HttpResponseMessage response;
        try
        {
            string owner = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            var connections = _iDataAccess.GetAllConnections().ToList();
            response = Request.CreateResponse(HttpStatusCode.OK, connections);
        }
        catch (Exception ex)
        {
            response = GetExceptionResponseMessage(ex);
        }

        return response;
    }
}

如前所述,Fiddler捕获的HTTP请求标头看起来还可以,并且ADAL.js userInfo.profile上的aud属性是正确的appid。

As mentioned the HTTP request header captured by Fiddler looks ok, and the aud property on my ADAL.js userInfo.profile is the correct appid.

关于可能缺少的任何建议?
请注意,这不是一个基于Web的本机应用程序,而是自托管的,这意味着该Web服务作为Windows服务在localhost上运行,而不是在IIS中运行。

Any suggestions on what might be missing? Note that this is not a native web based app, it's self-hosted, which means the web service is running on localhost as a windows service, and not in IIS.

我已将站点配置为使用HTTPS,但是无论HTTP或HTTPS流量如何,我都会遇到相同的问题。

I have configured the site to use HTTPS, but I get the same problem regardless of HTTP or HTTPS traffic.

感谢您的收听!

推荐答案

您需要声明 ConfigureAuth(appBuilder); 作为启动中的第一行.cs配置方法。您可以找到很好的解释此处说明为什么需要将其声明为第一个。

You need to declare the ConfigureAuth(appBuilder); as the first line in the Startup.cs Configuration method. You can find a good explanation here on why it need to be declared as the first.

这篇关于从AngularJS / ADAL.js客户端访问WebApI时出现401未经授权的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆