14
votes

I have an ASP.NET MVC 5 app that authenticates against Azure Active Directory. I wanted to enable SSL on it across the app. and hence leveraged global filters as follows:

public class FilterConfig
{
    /// <summary>
    /// Registers the global filters.
    /// </summary>
    /// <param name="filters">The filters.</param>
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new RequireHttpsAttribute());
    }
}

After this I also set 'Enable SSL' in the project's properties to true. This gave me the following SSL URL -> https://localhost:34567. I updated the project to have this in its IIS Express path under the 'Web Tab' under Servers in 'Project URL'. However on running the site I run in to the following error:

IDX10311: RequireNonce is 'true' (default) but validationContext.Nonce is null. A nonce cannot be validated. If you don't need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to 'false'.

I have auth. enabled on the site. I use Azure Active directory.

The security code is as follows:

app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectUri                    
            });

        app.UseWindowsAzureActiveDirectoryBearerAuthentication(
            new WindowsAzureActiveDirectoryBearerAuthenticationOptions
            {
                Audience = audience,
                Tenant = tenant,      
            });

The auth. values are being read from the web.config and are as follows:

<add key="ida:ClientId" value="<some_guid>" />
<add key="ida:Audience" value="https://localhost:34567/" />
<add key="ida:AADInstance" value="https://login.windows.net/{0}" />
<add key="ida:Tenant" value="microsoft.onmicrosoft.com" />
<add key="ida:PostLogoutRedirectUri" value="https://localhost:34567/" />

I tried setting RequireNonce to false as directed in the error message as follows:

ProtocolValidator = new OpenIdConnectProtocolValidator
                {
                    RequireNonce = false
                }

But this just resulted in an invalid request error.

Could someone help me understand what the problem is here? Everything worked great until SSL was enabled.

8
Think I figured this out. The app. details in Azure AD are hardwired to depend on the original HTTP endpoint. Will update this once I have validated my theory.Sudeep Unnikrishnan
I am getting this too...Prisoner ZERO
Please, did you manage to fix this bug? I'm in the same situation.Mastenka
Check my answer in this thread : stackoverflow.com/questions/39412570/…Kiran B

8 Answers

17
votes

You can ignore exceptions if the error message starts with OICE_20004 or contains IDX10311. Note: do it on your own risk.

Notifications = new OpenIdConnectAuthenticationNotifications()
{
    RedirectToIdentityProvider = (context) =>
    {
        // Ensure the URI is picked up dynamically from the request;
        string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Uri.PathAndQuery;
        context.ProtocolMessage.RedirectUri = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Uri.PathAndQuery;
        context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
        return Task.FromResult(0);
    },
    AuthenticationFailed = (context) =>
    {
        if (context.Exception.Message.StartsWith("OICE_20004") || context.Exception.Message.Contains("IDX10311"))
        {
            context.SkipToNextMiddleware();
            return Task.FromResult(0);
        }
        return Task.FromResult(0);
    },
}
9
votes

From the Azure management portal, check that your application under the corresponding active directory has the same Sign On URL and reply URL.

If they are not same, you will get this error.

This happens when you enable SSL because it changes only the sign on URL to the HTTPS URL while the reply URL remains the same HTTP URL.

Edit: Read on if you want to know exactly why this is happening,

When you try to access your app using the https URL, it sets a cookie with a unique number(nonce) in your browser and hits Azure AD for authentication. After authentication, the browser has to give access to that cookie. But since the sign on URL and reply URL are different the browser does not recognise your app and does not give access to that cookie and hence the application throws this error.

6
votes

I can reproduce this error by pressing back button couple of times on my web application, even after successful login. can you try these 2 things: in your code below:

app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = mViewWebSite.ClientId,
                    Authority = mViewWebSite.Authority,
                    PostLogoutRedirectUri = mViewWebSite.PostLogoutRedirectUri
                });

add protocol validator as on of the authentication options, as what error suggest:

ProtocolValidator = new Microsoft.IdentityModel.Protocols.OpenIdConnectProtocolValidator(){
                            RequireNonce = false
                        }

or add notification, by this you can catch this error and redirect it to some error page. I do that to make it graceful. Until Katana people fixes it.

Notifications = new OpenIdConnectAuthenticationNotifications
                        {
                            AuthenticationFailed = context =>
                            {
                                context.HandleResponse();
                                context.Response.Redirect("/Error.aspx?message=" + context.Exception.Message);
                                return Task.FromResult(0);
                            }
                        },
1
votes

I manage to work around this problem using following method in the Global.asax file. At least this won't show the exception to the client. I use ELMAH to catch exceptions.

protected void Application_Error(object sender, EventArgs args)
    {
        var ex = Server.GetLastError();
        if (ex.Message.Contains("IDX10311:"))
        {
            Server.ClearError();
            Response.Redirect("https://www.yoursitename.com");                 
        }
1
votes

Well it would probably be best to look at the katana source code, from that i found the exception type to be OpenIdConnectProtocolInvalidNonceException so i handle it like this.

        if (n.Exception is OpenIdConnectProtocolInvalidNonceException &&
            n.OwinContext.Authentication.User.Identity.IsAuthenticated)
        {
            n.SkipToNextMiddleware();
            return;
        }

I have this exception popup on browsers that cache the pages and users that click the back button after login.

1
votes

The issue here is simple... took me hours to figure this out. Since I was testing on my local had no https and to tell you the truth when initially creating my app in Azure AD since i wasnt expecting it to be https during my test I made it plain http (replyUrl's HomePage Url, Logout all that jazz)

Then after doing this i encountered the infinate loop issue a lot of people are getting. so then i decided to mock the cert on my local and yep that got rid of the infinate redirect but then brought another one the "IDX10311: RequireNonce is 'true' " one

Long story short... make your AzureAD App https in all its endpoints. and wallah!

1
votes

@zb3b answer + @jonmeyer answer:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    ...
    Notifications = new OpenIdConnectAuthenticationNotifications()
    {
        ...
        AuthenticationFailed = (context) =>
        {
            if ((context.Exception is OpenIdConnectProtocolInvalidNonceException) &&
                (context.OwinContext.Authentication.User.Identity.IsAuthenticated))
            {
                context.SkipToNextMiddleware();
                return Task.FromResult(0);
            }

            return Task.FromResult(0);
        },
        ...
    }
});
0
votes

Just adding another case I just ran into: the network you connect to may be modifying HTML content.

A customer called with an issue: he could not get past this error. It was a new laptop where he had not logged on before. After about one hour of trying several possible solutions, I decided to check the network he was connected to.

It turns out he was connected to a network in an airport, open and unsecured, and not using a VPN service (lacking some SETA there). I don't know exactly who operated that network or what they were doing, but the Azure AD service must have detected some type of tampering with the nonce.

The moment the user connected to a trusted network, the issue was resolved.