IDX21323 RequireNonce error with webforms app

I saw this thread from a few months back, but it had no actual answer, so I wanted to see if anyone else had run into this and knew what fixed it. Also I’m using the new Okta.AspNet library, which it isn’t clear the other poster had in place.

I’ve got an ASP.NET WebForms app using Okta.AspNet 1.1.1 for auth handling. For the most part it works fine, except for the occasional error for the /authorization-code/callback URL:

Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolInvalidNonceException
IDX21323: RequireNonce is '[PII is hidden]'. OpenIdConnectProtocolValidationContext.Nonce was null, OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce was not null. The nonce cannot be validated. If you don't need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to 'false'. Note if a 'nonce' is found it will be evaluated.

Most times AUTH_USER is set, but occasionally not.

My Startup class’ Configuration function:

Public Sub Configuration(app As IAppBuilder)
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)

    app.UseCookieAuthentication(New CookieAuthenticationOptions())

    Dim settingPrefix = EnvironmentSettingPrefix(app)
    Dim appSettings = ConfigurationManager.AppSettings

    Dim oktaPrefix = settingPrefix & OKTA_SETTING_PREFIX
    Dim options = New OktaMvcOptions With
        {
        .OktaDomain = appSettings.Item(oktaPrefix & "domain"),
        .ClientId = appSettings.Item(oktaPrefix & "clientId"),
        .ClientSecret = appSettings.Item(oktaPrefix & "clientSecret"),
        .RedirectUri = appSettings.Item(oktaPrefix & "redirectUri"),
        .PostLogoutRedirectUri = appSettings.Item(oktaPrefix & "postLogoutRedirectUri"),
        .AuthorizationServerId = appSettings.Item(oktaPrefix & "authorizationServerId"),
        .GetClaimsFromUserInfoEndpoint = True,
        .Scope = New List(Of String) From {"openid", "profile", "email"}
        }
    app.UseOktaMvc(options)
End Sub

That’s pretty much verbatim from the Okta ASP.NET Quickstart The other thread on this mentioned using UseExternalSignInCookie, but I’m new enough to ASP.NET to not know why that’d be necessary, given logins work for the most part.

Thanks.

I have the same problem - has anyone found a solution yet?

My solution was something of a hack, but seems to have worked. In Global.asax I updated Application_Error() to notice these problems and “re-auth” the user so we get a proper nonce.

I’m not enamored with this, due to the potential for a redirect loop, but that doesn’t seem to have happened, checking our logs.

Dim ex = Server.GetLastError()

' We often see invalid nonce errors where user's the ID token has a nonce, but the validation context does not.
' This is a hack solution to hopefully fix that. We simply re-challenge the client, which should bounce them through auth and back with a proper nonce.
' It's possible this could end up in a redirect loop. If we start seeing errors to that effect, we should try to detect when we've done this once, and stop.
If TypeOf ex Is Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolInvalidNonceException Then
    Context.GetOwinContext().Authentication.Challenge()
    Exit Sub
End If
1 Like

Thanks tleonard. I have achieved something similar using OWin Pipelines, but your post was the inspiration.

In my patch config file I added

  <sitecore>
    <pipelines>
      <owin.globalExceptionHandler>
        <processor type="MyProject.Authentication.Okta.Pipelines.ExceptionsHandler, MyProject.Authentication.Okta" resolve="true" />
      </owin.globalExceptionHandler>
    </pipelines>
  </sitecore>

And the class was implemented like so:

public class ExceptionsHandler : GlobalExceptionHandlerProcessor {
    public override void Process(GlobalExceptionHandlerArgs args) {
        Assert.ArgumentNotNull((object)args, nameof(args));
        string message = args.Exception.Message;
        var context = args.Context;

        if (message.StartsWith("IDX21323")) {
            args.Context.Response.Redirect("<where I need to>");
        }
    }
}