OpenIdConnectAuthenticationHandler:message.State为null或为空。连接到Azure Active Directory时

时间:2016-12-14 21:11:53

标签: c# azure asp.net-core asp.net-core-mvc azure-active-directory

我正在尝试使用我的应用程序连接到Azure Active Directory,但是我收到此错误: 处理请求时发生未处理的异常。

  

异常:OpenIdConnectAuthenticationHandler:message.State为null   或空的。未知位置

     

AggregateException:未处理的远程故障。   Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.d__5.MoveNext()

我的appsettings.json文件如下所示:

"AzureAd": {
    "ClientId": "<Application ID value from Azure Portal>",
    "AadInstance": "https://login.microsoftonline.com/{0}",
    "TenantId": "<tenant>.onmicrosoft.com",
    "AuthCallback": "/"
  }

和Startup.cs

  app.UseCookieAuthentication();

  app.UseIdentity();
  app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
  {
       ClientId = Configuration["AzureAd:ClientId"],
       Authority = string.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAd:TenantId"]),
       CallbackPath = Configuration["AzureAd:AuthCallback"]
  });

我在项目中启用了ssl,并添加了Visual Studio为我提供的URL作为回复网址。

之前,当我配置了错误的URL时,它引导我进入Microsoft登录站点,该站点表示该URL与任何已注册的URL都不匹配,所以我知道它至少已经达到了这一点。

我还应该说我正在关注this post,但是使用新的门户网站。我无法访问经典门户网站。

如何解决此错误?

感谢您的帮助。

3 个答案:

答案 0 :(得分:0)

当您提到新门户时,请确保它代表new Azure portal 代替new register apps portalAzure AD v2.0 endpoint

  

之前,当我配置了错误的URL时,它引导我进入Microsoft登录站点,该站点表示该URL与任何已注册的URL都不匹配,所以我知道它至少已经达到了这一点。

您在代码中使用的redirect_url应该针对您在Azure上注册的应用进行配置。

我也跟着这个链接,这个项目对我很有用。您可以从here下载项目。请先在Azure上为应用配置redirect_url(https://localhost:44397/signin-aad)并根据您的应用设置应用设置,然后您可以使用网址https://localhost:44397

访问该应用

答案 1 :(得分:0)

如果有人遇到此问题,请将事件处理程序添加到OnMessageReceived以调试请求。不知何故,我偶然发现将redirect_url设置为/ signin-oidc,该路径上的GET将具有一个空的上下文。属性当然会导致此特定错误

答案 2 :(得分:0)

我不确定是否相关,但是我遇到了类似的错误消息。 @rfcdejong通过建议调试OnMessageReceived为我指明了正确的方向。就我而言,我试图在Azure AD B2C中实现重设密码自定义流。它只用一个id_token来调用它。这使我意识到,此时我应该将用户重定向到主页-否则,我还会遇到message.State is null or empty错误。

我的代码如下: Startup.cs

services.Configure<OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme, options =>
{
    options.EventsType = typeof(CustomOpenIdConnectEvents);
});

,然后在CustomOpenIdConnectEvents中,我拥有:

    public class CustomOpenIdConnectEvents : OpenIdConnectEvents
    {
        ...

        public override async Task MessageReceived(MessageReceivedContext context)
        {
            // Set breakpoint in here to see what is happening

            if (!string.IsNullOrEmpty(context.ProtocolMessage.Error) && !string.IsNullOrEmpty(context.ProtocolMessage.ErrorDescription))
            {
                if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90118")) // forgot password
                {
                    context.HandleResponse();
                    context.Response.Redirect("/Account/ResetPassword");
                }
                else
                {
                    context.HandleResponse();
                    context.Response.Redirect("/");
                }
            }
            else
            {
                // On successful password reset we need to do this or we get a message.State is null or empty
                context.HandleResponse();
                context.Response.Redirect("/");
            }

            return;// Task.FromResult(0);

        }

也许值得一提的是,我对大多数人的做法有所不同。通常,您不会使用从OpenIdConnectEvents继承的自定义对象覆盖整个EventsType。取而代之的是,您可以在Startup.cs文件中这样做:

services.Configure<OpenIdConnectOptions>(options => 
{

    // ...

    options.Events = new OpenIdConnectEvents
    {
        OnMessageReceived = context =>
        {
            if (context.HttpContext.Request.Query.ContainsKey("error"))
            {
                context.HandleResponse(); // <-- Fires
                context.Response.Redirect("/AccessDenied"); // <-- Redirect fires but user is not redirected
            }

            return Task.FromResult(0);
        }
    }
}

而且,如果调试OnMessageReceived不能解决问题,您可能也想尝试OnRemoteFailureOnAuthenticationFailed