如何在ASP.NET Core 3上同时使用Azure AD身份验证和身份? [英] How to use both Azure AD authentication and Identity on ASP.NET Core 3?

查看:190
本文介绍了如何在ASP.NET Core 3上同时使用Azure AD身份验证和身份?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该Web应用程序应允许具有AD帐户的内部员工使用Azure AD身份验证在应用程序中进行身份验证.外部用户应该能够使用ASP.NET Core Identity注册和登录.我可以分别实现每个应用程序,但不能在同一应用程序中一起实现.当我将两个身份验证添加到同一应用程序时,ASP.NET Core Identity可以完美地工作.我可以毫无问题地使用Identity进行注册和登录.但是,当我尝试使用Azure AD登录时,应用程序将我重定向到租户的登录页面,我提交了用户名和密码,它将我重定向回应用程序,但未对用户进行身份验证.我再次点击登录按钮,同样的事情发生了.似乎该Web应用程序或浏览器没有保存访问令牌或类似的东西.

The web application should allow internal employees with AD accounts to authenticate in the app using Azure AD Authentication. External users should be able to register and sign in using ASP.NET Core Identity. I can implement each one separately but not together in the same app. When I add both authentications to the same app, the ASP.NET Core Identity works perfectly. I can register and log in using Identity with no problem. However when I try to log in with Azure AD, the app redirects me to my tenant's login page, I submit a username and password, it redirects me back to the application but no user is authenticated. I hit the login button again and the same thing happens. It seems that the web app or browser is not saving the access token or something like that.

我在做什么错?甚至可以在同一应用程序上进行两组身份验证吗?

谢谢.这是代码:

<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1">

启动类

public IConfiguration Configuration { get; }

public Startup(IConfiguration configuration) => Configuration = configuration;

public void ConfigureServices(IServiceCollection services)
{
    //  Add Azure AD authentication
    services.AddAuthentication(defaultScheme: AzureADDefaults.AuthenticationScheme)
        .AddAzureAD(options => Configuration.Bind("AzureAd", options));

    //  Add the application db context
    services.AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    //  Add Identity using Entity Framework Core
    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<AppDbContext>()
        .AddDefaultTokenProviders();

    //  Configure Identity
    services.Configure<IdentityOptions>(options =>
    {
        // Password settings.
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = true;
    });

    services.AddMvc();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseDeveloperExceptionPage();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseEndpoints(endpoints => endpoints.MapControllers());
}

用户控制器

这是一个自定义控制器,我们在其中处理与身份验证相关的HTTP请求.

User Controller

This is a custom controller where we handle HTTP requests related to authentication.

private readonly UserManager<ApplicationUser> userManager;
private readonly SignInManager<ApplicationUser> signInManager;

public UserController(UserManager<ApplicationUser> um, SignInManager<ApplicationUser> sm) =>
     (userManager, signInManager) = (um, sm);

//  Internal employee users will authenticate using Azure AD
[HttpGet("internal-signin")]
public ChallengeResult InternalSignIn(string returnUrl = "/") => 
     Challenge(new AuthenticationProperties { RedirectUri = returnUrl }, AzureADDefaults.AuthenticationScheme);

//  Display view with a form to create a new external user account
[HttpGet("register")]
public ViewResult Register() => View();

//  Create a new account for an external user
[HttpPost("register")]
public async Task<IActionResult> Register(RegistrationInputModel inputModel)
{
    //  Check if the model state is valid
    if (!ModelState.IsValid)
    {
        //  Redirect to the Register view
        return View(viewName: nameof(Register), model: inputModel);
    }

    //  Create an application user object
    ApplicationUser user = new ApplicationUser
    {
        //  Map the fields of the input model with the user
        UserName = inputModel.Email,
        Email = inputModel.Email,
        FirstName = inputModel.FirstName,
        LastName = inputModel.LastName,
        Company = inputModel.CompanyName,
    };

    //  Try to register the user on the database
    IdentityResult result = await userManager.CreateAsync(user, inputModel.Password);

    //  If failed, then set the error messages into the model state
    if (!result.Succeeded)
    {
        foreach (IdentityError error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }

        //  Return the user to the registration view
        return View(viewName: nameof(Register), model: inputModel);
    }

    //  Sign In the user
    await signInManager.SignInAsync(user, isPersistent: false);

    //  Otherwise, redirect the user to the index page
    return RedirectToAction(nameof(HomeController.Index), controllerName: "Home");
}

//  External users sign out action
[HttpGet("signout")]
[Authorize]
public async Task<IActionResult> SignOut()
{
    await signInManager.SignOutAsync();
    return RedirectToAction(nameof(HomeController.Index), "Home");
}

//  Display form to login for external users
[HttpGet("signin")]
public ViewResult SignIn() => View();

//  Login an external user
[HttpPost("signin")]
public async Task<IActionResult> SingIn(SingInInputModel inputModel)
{
    //  Check if the model state is valid
    if (!ModelState.IsValid)
    {
        //  Send the user back to the sign in view
        return View(viewName: nameof(SignIn), model: inputModel);
    }

    //  Try to sign in the user
    SignInResult result = await signInManager
        .PasswordSignInAsync(inputModel.Email, inputModel.Password, inputModel.RememberMe, lockoutOnFailure: false);

    //  Check if the login was unsuccessful
    if (!result.Succeeded)
    {
        ModelState.AddModelError(string.Empty, "Invalid login attempt.");
        return View(viewName: nameof(SignIn), model: inputModel);
    }

    //  Send the user back to the index page
    return RedirectToAction(nameof(HomeController.Index), "Home");
}

应用程序用户

public class ApplicationUser : Microsoft.AspNetCore.Identity.IdentityUser
{
     public string FirstName { get; set; }
     public string LastName { get; set; }
     public string Company { get; set; }
}

推荐答案

如果将ASP.NET Core Identity与Azure AD登录一起使用,则可以将CookieSchemeName设置为Identity.External,以便asp.net Core Identity可以获取外部来自外部身份提供者的用户个人资料,并创建与外部用户相关联的本地用户:

If using ASP.NET Core Identity with Azure AD login , you can set CookieSchemeName to Identity.External so that asp.net core identity can get the external user profile from external identity provider , and create a local user associated with external user :

在appsettings.json中:

In appsettings.json :

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "peterpad.onmicrosoft.com",
    "TenantId": "cb1c3f2e-a2dd-4fde-bf8f-f75ab18b21ac",
    "ClientId": "0c0ec562-a9bb-4722-b615-6dcbdc646326",
    "CallbackPath": "/signin-oidc",
    "CookieSchemeName": "Identity.External"
},

然后,如果您想挑战MVC控制器中的Azure AD登录,则应提供方案名称,身份验证后的配置重定向url至Identity/Account/ExternalLoginCallback处理程序,在该处理程序中,asp.net核心标识将允许您输入用户名并创建本地用户:

Then if you want to challenge Azure AD login in MVC controller , you should provide the scheme name , config redirect url after authentication to Identity/Account/ExternalLoginand Callbackhandler , in that handler asp.net core identity will let your enter username and create a local user :

[HttpGet("internal-signin")]
public ChallengeResult InternalSignIn(string returnUrl = "/") 
{
    var redirectUrl = Url.Page("/Account/ExternalLogin", pageHandler: "Callback", values: new { returnUrl , area = "Identity" });
    var properties = _signInManager.ConfigureExternalAuthenticationProperties(AzureADDefaults.AuthenticationScheme, redirectUrl);
    return new ChallengeResult(AzureADDefaults.AuthenticationScheme, properties);
}

这篇关于如何在ASP.NET Core 3上同时使用Azure AD身份验证和身份?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆