Azure-Samples / active-directory-aspnetcore-webapp-openidconnect-v2

An ASP.NET Core Web App which lets sign-in users (including in your org, many orgs, orgs + personal accounts, sovereign clouds) and call Web APIs (including Microsoft Graph)
MIT License
1.36k stars 986 forks source link

login and authneticate using both Individual User Accounts and Azure AD Authentication #780

Open VikneshSubramaniyan opened 1 month ago

VikneshSubramaniyan commented 1 month ago

Microsoft.Identity.Web version

2.18.0

Web app sign-in

1-WebApp-OIDC/1-1-MyOrg

Web API (call Graph or downstream APIs)

2-WebApp-graph-user/2-1-Call-MSGraph

Deploy to Azure

5-WebApp-AuthZ/5-1-Roles

Auth Z

6-Deploy-to-Azure

Description

I implemented the code like performing both microsoft authentication and local identity authentication..when i login using micrsoft authentication,its working fine..when tried to login using local identity its authenticated but redirected to login page again...AddAuthentication() has issue about that.. can any one explain how can i manage both authentication ,is that possile? isthere suggestion to sort out this? Startup.cs `

using System;
using Dapper;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Serialization;
using Piranha;
using Piranha.AttributeBuilder;
using Piranha.ImageSharp;
using Piranha.Local;
using SendbackPortal.Data;
using SendbackPortal.Models;
using SendbackPortal.Models.Templates;
using SendbackPortal.Repositories;
using SendbackPortal.Services;
using EntityFrameworkCore.UseRowNumberForPaging;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Identity.Web.UI;
using Piranha.Data.EF.SQLServer;
using Piranha.Manager.Editor;
using Piranha.Manager.LocalAuth;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using SendbackPortal.Models.AccountViewModels;

namespace SendbackPortal
{
    public class Startup
    {
        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {
            Configuration = configuration;
            var contentRoot = configuration.GetValue<string>(WebHostDefaults.ContentRootKey);
        }

        public IConfiguration Configuration { get; }
        public string conn;

        public void ConfigureServices(IServiceCollection services)
        {
            var defaultConnection = Configuration.GetConnectionString("DefaultConnection");
            var advConnection = Configuration.GetConnectionString("ADVConnection");

            services.AddTransient<IClaimsTransformation, CustomClaimsTransformation>();

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(defaultConnection, b => b.UseRowNumberForPaging()));
            services.AddDbContext<SQLServerDb>(options =>
                options.UseSqlServer(defaultConnection, b => b.UseRowNumberForPaging()));
            services.AddDbContext<DefaultDBContext>(options =>
                options.UseSqlServer(defaultConnection, b => b.UseRowNumberForPaging()));
            services.AddDbContext<AdvDbContext>(options =>
                options.UseSqlServer(advConnection, b => b.UseRowNumberForPaging()));

            services.AddDistributedMemoryCache();

            services.AddIdentity<ApplicationUser, IdentityRole>(options => {
                options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+/' ";
            })
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders()
            .AddErrorDescriber<CustomIdentityErrorDescriber>();

            services.Configure<DataProtectionTokenProviderOptions>(o => o.TokenLifespan = TimeSpan.FromDays(14));

            services.AddSingleton(Configuration);
            services.AddSingleton<IStorage, FileStorage>();
            services.AddSingleton<IImageProcessor, ImageSharpProcessor>();
            services.AddTransient<ISecurity, IdentitySecurity>();
            services.AddScoped<IDb, SQLServerDb>();
            services.AddScoped<IApi, Api>();

            services.AddPiranha(options =>
            {
                options.UseCms();
                options.UseManager();
                options.UseFileStorage(naming: Piranha.Local.FileStorageNaming.UniqueFolderNames);
                options.UseImageSharp();
                options.UseTinyMCE();
                options.UseEF<SQLServerDb>(db =>
                    db.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            });

            services.AddTransient<IEmailSender, EmailSender>();
            services.AddTransient<IUserRepository, UserRepository>();
            services.AddTransient<ISendbackRepository, SendbackRepository>();
            services.AddTransient<IEntraClaimInterface, IEntraClaim>();
            services.AddTransient<IUsersMappingRepository, UsersMappingRepository>();
            services.AddTransient<IPhysicianMessengerRepository, PhysicianMessengerRepository>();
            services.AddTransient<ILocationExclusionRepository, LocationExclusionRepository>();

            services.AddSession();

            // Add Microsoft authentication
            services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

            services.AddControllersWithViews(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            }).AddMicrosoftIdentityUI();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider services)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            DefaultTypeMap.MatchNamesWithUnderscores = true;

            var api = services.GetService<IApi>();
            App.Init(api);

            var pageTypeBuilder = new ContentTypeBuilder(api)
                .AddType(typeof(BlogArchive))
                .AddType(typeof(StandardPage));
            pageTypeBuilder.Build();
            var postTypeBuilder = new ContentTypeBuilder(api)
                .AddType(typeof(BlogPost));
            postTypeBuilder.Build();
            EditorConfig.FromFile("editorconfig.json");

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseMiddleware<PasswordMiddleware>();

            app.UsePiranha(options =>
            {
                options.UseManager();
                options.UseTinyMCE();
            });

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapControllerRoute(
                    name: "areaRoute",
                    pattern: "{area:exists}/{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });
                endpoints.MapPiranhaManager();
            });
        }
    }
}

external login api `

`[HttpPost]
 [AllowAnonymous]

 public async Task<IActionResult> ExternalLogin(string provider, string returnUrl = null)
 {
     var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
     var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
     return Challenge(properties, provider);
 }

 [HttpGet]
 [AllowAnonymous]
 //[Authorize(Policy = "MicrosoftIdentityPolicy")]
 public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
 {
     // Handle the error if there's any
     if (remoteError != null)
     {
         // Log the error or handle it as needed
         return RedirectToAction(nameof(Login));
     }

     // Check if the user is already signed in
     if (User.Identity.IsAuthenticated)
     {
         // If the user is already signed in, just redirect to the return URL
         return LocalRedirect(returnUrl ?? "~/");
     }

     // Retrieve the user information from the external authentication provider
     // This is an example using claims directly
     var email = User.FindFirstValue(ClaimTypes.Email);

     if (string.IsNullOrEmpty(email))
     {
         // Handle missing email case or other user identification details
         return RedirectToAction(nameof(Login));
     }

     // Retrieve the user from the database using UserManager
     var user = await _userManager.FindByEmailAsync(email);

     if (user == null)
     {
         // Handle case where the user does not exist in the local database
         // Create a new user if needed
         user = new ApplicationUser { UserName = email, Email = email };
         var createResult = await _userManager.CreateAsync(user);
         if (!createResult.Succeeded)
         {
             // Handle user creation failure
             return RedirectToAction(nameof(Login));
         }
     }

     // Sign in the user
     await _signInManager.SignInAsync(user, isPersistent: false);

     // Redirect to the return URL or default route
     return LocalRedirect(returnUrl ?? "~/");
}`

i need to how handle both local authnetication and microsoft authentication in single application

Reproduction steps

none

Error message

No response

Id Web logs

No response

Relevant code snippets

None

Regression

No response

Expected behavior

I need to authenticate user data using both authentication like asp.net identity authentication and Microsoft authentication