带有 OWIN - 授权质询的 WebApi 2 不会重定向到登录



我正在尝试利用带有OpenIdConnect 身份验证的OWIN登录Azure Active Directory。 我的应用程序是使用 WebApi 2 的 ASP .NET。 在这一点上,前端只是简单的HTML/Javascript。 在本地运行我的应用程序时,我在控制器上调用 WebApi(控制器和任何 API 都没有 [授权] 过滤器),该 API 反过来使用当前的 OWIN 上下文来质询身份验证。 此质询按预期失败,因为我未登录并继续调用"https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=..."这也是意料之中的。 请求返回 200 状态,响应包含Microsoft登录页面的 HTML。 但是,我的 Web 应用程序不会重定向到该登录页面,并且控制台显示 CORS 错误:

无法加载 https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=[removed]&redirect_uri=http%3a%2f%2flocalhost%3a20776%2f&response_mode=form_post&response_type=code+id_token&scope=openid+email+profile+offline_access+User.Read+Mail.Send+Files.ReadWrite&state=OpenIdConnect.AuthenticationProperties[removed]:

对预检请求的响应未通过访问控制检查:请求的资源上不存在"访问控制允许源"标头。因此,不允许访问源"http://localhost:20776"。

我用浏览器扩展程序强行解决了 CORS 问题,但即便如此,它也没有重定向到签名页面。 相反,响应像以前一样包含登录页面的源。 我在下面概述了我采取的步骤和我正在使用的代码。 我错过了一步吗?

我发现的大多数文档和示例都 ASP.NET 利用了MVC。 我的大部分实现都基于此处的 MVC 示例:https://github.com/Azure-Samples/active-directory-dotnet-webapp-groupclaims

该示例在本地运行良好,我能够使用 AAD 凭据登录并成功调用 MS 图形 API。

至于 CORS 问题,我在 MVC 示例中没有看到这一点。 为什么此 CORS 问题出现在我当前的设置中,我该如何解决它? 我希望 OWIN 中间件能够解决这个问题。 在控制器上使用 EnableCors 过滤器没有帮助,在 IAppBuilder 上启用 CORS 也没有帮助。

我期望的 Web 请求是(基于 OWIN MCV 示例):

//Call to sign in which initiates the challenge
Request URL:http://localhost:55065/Account/SignIn
Request Method:GET
Status Code:302 Found
Remote Address:[::1]:55065
Referrer Policy:no-referrer-when-downgrade
//Call to perform the challenge.  Should redirect to MS login after this
Request 
URL:https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=[truncated]
Request Method:GET
Status Code:200 OK
Remote Address:104.42.72.20:443
Referrer Policy:no-referrer-when-downgrade

我实际上在我的 WebApi 项目中看到的 Web 请求是:

Request URL:http://localhost:13291/api/v1/tools/user/signin
Request Method:GET
Status Code:302 Found
Remote Address:[::1]:13291
Referrer Policy:no-referrer-when-downgrade
Request URL:http://localhost:13291/api/v1/tools/user/signin
Request Method:POST
Status Code:302 Found
Remote Address:[::1]:13291
Referrer Policy:no-referrer-when-downgrade
Request URL:https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=[truncated]
Request Method:OPTIONS
Status Code:200 OK
Remote Address:104.210.48.14:443
Referrer Policy:no-referrer-when-downgrade
Request URL:https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=[truncated]
Request Method:GET
Status Code:200 OK
Remote Address:104.210.48.14:443
Referrer Policy:no-referrer-when-downgrade

以下是我的设置摘要,后跟相关代码:

  • 通过 Azure AD 注册了一个新应用程序,回复 URL 为 http://localhost:13291,以匹配我在本地运行的内容。
  • 我使用与 OpenIdConnectionAuthenticationOptions 的重定向 URI 相同的 URL
  • 我使用已注册应用程序的 AppID 作为 OpenIdConnectionAuthenticationOptions 的 CliendID
  • React 正在使用 JQuery $.post
  • 启用 CORS 的唯一位置是 OWIN 启动类中的 IAppBuilder

代码摘录为了简洁起见,我删除了命名空间定义和一些类定义。 下面的代码来自我创建的一个新的最小示例,用于在我正在处理的更大的 Web 应用程序之外重现问题。 前端只是一个简单的JQuery调用。 我想提供对该解决方案的访问权限,但它目前包含我的 AppSecret,我相信甚至需要尝试重现它。

WebApiConfig.cs

public static HttpConfiguration Register()
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
return config;
}

启动.cs

[assembly: OwinStartup(typeof(Startup))]
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}

Startup.Auth.cs

public partial class Startup
{
//...
//Obtain various application settings
//...
public void ConfigureAuth(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);  
app.SetDefaultSignInAsAuthenticationType( CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = appId,
Authority = "https://login.microsoftonline.com/common/v2.0",
PostLogoutRedirectUri = redirectUri,
RedirectUri = redirectUri,  //http://localhost:13291
TokenValidationParameters = ...,
Notifications = ...,
AuthenticationFailed = ...
}
app.UseWebApi(WebApiConfig.Register());
}
}

Foo控制器.cs

public class FooController : ApiController
{
[Route("api/v1/tools/user/signin")]
[HttpPost]
public HttpResponseMessage SignIn()
{
if (HttpContext.Current.User == null || HttpContext.Current.User.Identity.IsAuthenticated == false)
{
var properties = new AuthenticationProperties() {RedirectUri = "/"};
Request.GetOwinContext().Authentication
.Challenge(properties, OpenIdConnectAuthenticationDefaults.AuthenticationType);
return Request.CreateResponse(HttpStatusCode.Unauthorized);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
}

索引.html

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
function signIn() {
$.post("/api/v1/tools/user/signin", (r) => {
}).fail((e) => {
console.log(e);
});
}
</script>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input id="signIn" type="button" value="SignIn" onclick="signIn();" />
</body>
</html>

https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas 看看这个,它帮助我处理了来自我的 Web API 上 angular 的跨域请求

最新更新