从 AngularJS/ADAL.js 客户端访问 WebApI 时出现 401 Unauthorized 错误
401 Unauthorized errors when accessing WebApI from AngularJS/ADAL.js client
我有一个带有 angular 前端的 self-hosted 网络 api 应用程序,现在我需要开始通过 Azure Active Directory 对用户进行身份验证。
我已经下载了 SinglePageApp 示例并进行了设置并成功 运行。
https://github.com/Azure-Samples/active-directory-angularjs-singlepageapp-dotnet-webapi
当对我自己的应用程序进行必要的更改时,我可以成功地将用户重定向到 Azure 登录屏幕并使用 adal.js/adal_angular.js 取回 userProfile。每当我调用我的 API 时,我都会收到 401 未经授权的错误,但是使用 Fiddler,我可以看到在每次调用中都将承载令牌添加到 HTTP header。
这是我的 AdalAngular 设置:
.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 代码:
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);
}
我的 app.config 中的 ActiveDirectoryTenant 和 ActiveDirectoryApplicationId 与我的 angular adalProvider.init 代码中的配置完全匹配。
最后,我的 ApiController 看起来像这样:
[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 请求 header 看起来没问题,我的 ADAL.js userInfo.profile 上的 aud 属性 是正确的 appid。
对可能遗漏的内容有什么建议吗?
请注意,这不是基于 Web 的本机应用程序,它是 self-hosted,这意味着 Web 服务在本地主机上是 运行 作为 windows 服务,而不是在 IIS 中。
我已将站点配置为使用 HTTPS,但无论 HTTP 还是 HTTPS 流量,我都会遇到同样的问题。
感谢收听!
您需要将 ConfigureAuth(appBuilder);
声明为 Startup.cs 配置方法中的第一行。你可以找到一个很好的解释为什么它需要声明为第一个。
我有一个带有 angular 前端的 self-hosted 网络 api 应用程序,现在我需要开始通过 Azure Active Directory 对用户进行身份验证。
我已经下载了 SinglePageApp 示例并进行了设置并成功 运行。 https://github.com/Azure-Samples/active-directory-angularjs-singlepageapp-dotnet-webapi
当对我自己的应用程序进行必要的更改时,我可以成功地将用户重定向到 Azure 登录屏幕并使用 adal.js/adal_angular.js 取回 userProfile。每当我调用我的 API 时,我都会收到 401 未经授权的错误,但是使用 Fiddler,我可以看到在每次调用中都将承载令牌添加到 HTTP header。
这是我的 AdalAngular 设置:
.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 代码:
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);
}
我的 app.config 中的 ActiveDirectoryTenant 和 ActiveDirectoryApplicationId 与我的 angular adalProvider.init 代码中的配置完全匹配。
最后,我的 ApiController 看起来像这样:
[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 请求 header 看起来没问题,我的 ADAL.js userInfo.profile 上的 aud 属性 是正确的 appid。
对可能遗漏的内容有什么建议吗? 请注意,这不是基于 Web 的本机应用程序,它是 self-hosted,这意味着 Web 服务在本地主机上是 运行 作为 windows 服务,而不是在 IIS 中。
我已将站点配置为使用 HTTPS,但无论 HTTP 还是 HTTPS 流量,我都会遇到同样的问题。
感谢收听!
您需要将 ConfigureAuth(appBuilder);
声明为 Startup.cs 配置方法中的第一行。你可以找到一个很好的解释