Share via

ErrorMessage-IDX21323

Oded Mayost 0 Reputation points
2023-12-20T09:27:55.02+00:00

I have a project whose login process is performed using Azure AD and Microsoft Graph.

I would appreciate help with the attached bug - this bug only happens when I use the Google Chrome or Microsoft Edge browser, when I use the Mozilla browser I don't get the error and the process works as it should.

ErrorMessage-IDX21323: RequireNonce is 'True'. 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.

using System;
using System.Text;
using System.Threading.Tasks;
using Owin;
using Microsoft.Owin.Security;
using Microsoft.Identity.Client;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security.Cookies;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Owin.Security.Notifications;
using Microsoft.Owin.Security.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
// all my private projects using

namespace Website
{
    public partial class Startup
    {
        private static readonly ILoggerProvider logger = IoC.Resolve<ILoggerProvider>();

        private static readonly AzureADSettings azureADSettings = IoC.Resolve<AzureADSettingsFactory>().GetAzureADSettings();
        private static readonly string redirectURI = IoC.Resolve<IConfigParameterFactory>().Build("/SSO/AzureAD/RedirectURL", String.Empty).Value;
        private static readonly string graphScopes = IoC.Resolve<IConfigParameterFactory>().Build("/AzureAD/GraphScopes", "User.Read.All").Value;

        public void ConfigureAuth(IAppBuilder app)
        {
            string authority = $"https://login.microsoftonline.com/{azureADSettings.TenantID}/v2.0";
            string scope = $"openid email profile offline_access {graphScopes}";
            string responseType = OpenIdConnectResponseType.CodeIdToken;
            TokenValidationParameters tokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true };
            OpenIdConnectAuthenticationNotifications notifications = new OpenIdConnectAuthenticationNotifications
                                                                     {
                                                                         AuthenticationFailed = OnAuthenticationFailedAsync,
                                                                         AuthorizationCodeReceived = OnAuthorizationCodeReceivedAsync
                                                                     };

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId = azureADSettings.AppID,
                ClientSecret = azureADSettings.AppSecret,
                RedirectUri = redirectURI,
                Authority = authority,
                Scope = scope,
                ResponseType = responseType,
                TokenValidationParameters = tokenValidationParameters,                
                Notifications = notifications
            });
        }

        private static Task OnAuthenticationFailedAsync(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
        {
            notification.HandleResponse();

            string errorMessage = $"message-{notification.Exception.Message}";
            if (notification.ProtocolMessage != null && !string.IsNullOrEmpty(notification.ProtocolMessage.ErrorDescription))
            {
                errorMessage += $"--debug-{notification.ProtocolMessage.ErrorDescription}";
            }
            string errorCode = UserLoginFailed(errorMessage);

            string redirectURL = $"{LandingPageEndpoints.ssoErrorPage}?{LandingPageEndpoints.loginErrorUrlPropertyName}={errorCode}";
            notification.Response.Redirect(redirectURL);

            return Task.FromResult(0);
        }

        private async Task OnAuthorizationCodeReceivedAsync(AuthorizationCodeReceivedNotification notification)
        {
            notification.HandleCodeRedemption();

            IConfidentialClientApplication idClient =
                ConfidentialClientApplicationBuilder.Create(azureADSettings.AppID)
                                                    .WithTenantId(azureADSettings.TenantID)
                                                    .WithRedirectUri(redirectURI)
                                                    .WithClientSecret(azureADSettings.AppSecret)
                                                    .Build();

            string redirectURL = String.Empty;

            try
            {
                string[] scopes = graphScopes.Split(' ');

                AuthenticationResult result = await idClient.AcquireTokenByAuthorizationCode(scopes, notification.Code).ExecuteAsync();

                string userToken = EncodeToken(result.AccessToken);

                redirectURL = $"{LandingPageEndpoints.ssoAzureADPage}?{LandingPageEndpoints.userTokenUrlPropertyName}={userToken}";
            }
            catch (MsalException ex)
            {
                string errorMessage = $"AcquireTokenByAuthorizationCodeAsync threw an exception - {ex.Message}";

                string errorCode = UserLoginFailed(errorMessage);

                redirectURL = $"{LandingPageEndpoints.ssoErrorPage}?{LandingPageEndpoints.loginErrorUrlPropertyName}={errorCode}";
            }
            catch (Microsoft.Graph.ServiceException ex)
            {
                string errorMessage = $"GetUserDetailsAsync threw an exception - {ex.Message}";

                string errorCode = UserLoginFailed(errorMessage);

                redirectURL = $"{LandingPageEndpoints.ssoErrorPage}?{LandingPageEndpoints.loginErrorUrlPropertyName}={errorCode}";
            }

            notification.HandleResponse();
            notification.Response.Redirect(redirectURL);
        }

        private static string EncodeToken(string userToken)
        {
            // My encoding logic

            return encodedUserToken;
        }

        private static string UserLoginFailed(string errorMessage)
        {
            // My Logger

            return ErrorID;
        }
    }
}



Microsoft Security | Microsoft Entra | Microsoft Entra ID
Microsoft Security | Microsoft Graph
0 comments No comments

1 answer

Sort by: Most helpful
  1. Crystal Lee Morgan 380 Reputation points
    2023-12-20T17:46:28.99+00:00

    @Oded Mayost The error message you are seeing is related to the nonce validation in OpenID Connect protocol. The error message indicates that the nonce value was not validated because it was null. This error can occur when the nonce value is not included in the authentication request or when the nonce value is not returned in the ID token.

    The solution to this error is to set the RequireNonce property to false in the OpenIdConnectProtocolValidator class. This will disable the nonce validation and allow the authentication process to proceed without errors. Here is an example of how to set the RequireNonce property to false: (see below)

    If you still face issues, you can try the following steps:

    1. Clear your browser cache and cookies.
    2. Try using a different browser.
    3. Check if the issue persists with a different device or network.
    4. Ensure that the authentication request includes the nonce value.
    5. Ensure that the ID token returned by Azure AD includes the nonce value.

    If none of these solutions work, you can try contacting Azure DevOps support for further assistance. I hope this helps!

    C#
    
    var openIdConnectOptions = new OpenIdConnectOptions
    {
        // Other options...
        ProtocolValidator = new OpenIdConnectProtocolValidator
        {
            RequireNonce = false
        }
    };
    

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.