How to implement normal login and azure ad sso login in asp.net mvc?

ZST Test 1 Reputation point
2022-11-17T05:32:09.847+00:00

I want an asp.net web application with SSO login and normal login. I have followed all the steps from the Microsoft Document (https://learn.microsoft.com/en-us/azure/active-directory/develop/web-app-quickstart?pivots=devlang-aspnet).

SSO login works fine but I was not able to login using normal login. If I revert the changes I made for the SSO login normal login works. I have combined the normal login and SSO login authentication integrated in startup.cs. When I do this, the Microsoft login goes on an loop mode signing in again and again.

I have attached my startup.cs file. Could anyone help me out?

I have tried using

app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);  

before using

app.UseOpenIdConnectAuthentication  

My startup.cs file

public void Configuration(IAppBuilder app)   
{  
    // The Client ID is used by the application to uniquely identify itself to Azure AD.  
    string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];  
  
    // RedirectUri is the URL where the user will be redirected to after they sign in.  
    string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];  
  
    // Tenant is the tenant ID (e.g. contoso.onmicrosoft.com, or 'common' for multi-tenant)  
    string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];  
  
    // Authority is the URL for authority, composed by Microsoft identity platform endpoint and the tenant name (e.g. https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0)  
    string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);  
  
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);  
  
    var timeoutInMinutes = Convert.ToDouble(ConfigurationManager.AppSettings["SessionExpireInMinutes"]);  
  
    // Configure the db context, user manager and signin manager to use a single instance per request  
    app.CreatePerOwinContext(ApplicationDbContext.Create);  
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);  
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);  
  
    app.UseCookieAuthentication(new CookieAuthenticationOptions  
            {  
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,  
                LoginPath = new PathString("/Account/Login"),  
                Provider = new CookieAuthenticationProvider  
                {  
                    // Enables the application to validate the security stamp when the user logs in.  
                    // This is a security feature which is used when you change a password or add an external login to your account.    
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(  
                        validateInterval: TimeSpan.FromMinutes(30),  
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),  
                    OnResponseSignIn = context =>  
                    {  
                        context.Properties.IsPersistent = false;  
                        context.Properties.AllowRefresh = true;  
                        context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(timeoutInMinutes);  
                    }  
                },  
                SlidingExpiration = true  
            });  
  
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);  
  
    // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.  
    app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));  
  
    // Enables the application to remember the second login verification factor such as phone or email.  
    // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.  
    // This is similar to the RememberMe option when you log in.  
    app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);  
              
    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions  
            {                  
                AuthenticationMode = AuthenticationMode.Passive,  
                // Sets the client ID, authority, and redirect URI as obtained from Web.config  
                ClientId = clientId,  
                Authority = authority,  
                RedirectUri = redirectUri,  
                // PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it's using the home page  
                PostLogoutRedirectUri = redirectUri,  
                Scope = OpenIdConnectScope.OpenIdProfile,  
                // ResponseType is set to request the code id_token, which contains basic information about the signed-in user  
                ResponseType = OpenIdConnectResponseType.CodeIdToken,  
                // ValidateIssuer set to false to allow personal and work accounts from any organization to sign in to your application  
                // To only allow users from a single organization, set ValidateIssuer to true and the 'tenant' setting in Web.config to the tenant name  
                // To allow users from only a list of specific organizations, set ValidateIssuer to true and use the ValidIssuers parameter  
                TokenValidationParameters = new TokenValidationParameters()  
                {  
                    ValidateIssuer = false // Simplification (see note below)  
                },  
                // OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to the OnAuthenticationFailed method  
                Notifications = new OpenIdConnectAuthenticationNotifications  
                {  
                    AuthenticationFailed = OnAuthenticationFailed  
                }  
    });  
}  
  
/// <summary>  
/// Handle failed authentication requests by redirecting the user to the home page with an error in the query string  
/// </summary>  
/// <param name="context"></param>  
/// <returns></returns>  
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)  
{  
    context.HandleResponse();  
    context.Response.Redirect("/?errormessage=" + context.Exception.Message);  
    return Task.FromResult(0);  
}  
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,219 questions
Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
19,090 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Shweta Mathur 26,721 Reputation points Microsoft Employee
    2022-11-18T08:12:30.607+00:00

    Hi @ZST Test ,

    Thanks for reaching out.

    There might be few possible scenarios to avoid this issue:

    1.Commenting out the below lines from above code, stooped the redirect loop.

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login")
    });

    2.This issue is because of the authentication mode selected by the MVC Template, which triggers the ReturnUrl Style of redirection that might lead to an infinite loop if not configured correctly.

    To disable OWIN startup discovery, add this key to your webconfig file.

    <add key="owin:AutomaticAppStartup" value="false"/>

    3.You have to check AllowAnonymous and Authorize attribute in the controller containing login action and adding allowAnonymous might help to solve this issue.

    4.Check the redirect URI has been configured correctly and not have extra '/' which is also the possible reason for redirect loop.

    Hope this will help.

    Thanks,
    Shweta


    Please remember to "Accept Answer" if answer helped you.

    0 comments No comments

  2. Beau Claar 1 Reputation point
    2022-12-19T22:02:38.047+00:00

    Are you using Identity 2.0 to store your logins?
    Are you using an Azure AD v2 tenant (i.e. your company has Azure AD setup) or are you using generic Microsoft Accounts (i.e. .hotmail.com/.live.com)?

    If you are using your own tenant then the problem lies in the below...
    AccountController specifically at the ExternalLoginCallback

    0 comments No comments