可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
回答1:
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);
},
}
回答2:
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.
回答3:
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);
}
},
回答4:
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");
}
回答5:
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.
回答6:
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!
回答7:
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.
回答8:
@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);
},
...
}
});