用于身份验证的Azure Active Directory和用于授权的ASP.NET Core Identity

jim*_*lad 12 asp.net-core asp.net-core-2.0

我想创建一个ASP.NET Core 2.0应用程序,它使用Azure Active Directory作为身份提供程序(用于身份验证),但使用ASP.NET Core Identity进行授权(例如使用控制器属性,如'[Authorize(Roles ="Admin")] ").在解决方案中,我希望本地Identity数据库表AspNetUserLogins保存对Azure Active Directory标识的引用

我认为该解决方案将涉及声明转换,以使用从ASP.NET Core Identity获取的角色来装饰经过身份验证的用户.

我的问题:

  1. 我可以从Visual Studio解决方案模板中获取Azure Active Directory身份验证,但是我无法弄清楚如何在Startup.ConfigureServices()中的某处添加和配置ASP.NET核心身份(例如services.AddIdentity()等)
  2. 我想知道正确的钩子在哪里进行索赔转换.(例如OpenIdConnectEvents.OnTokenValidated或者可能是AccountController方法)

重现我的基线的步骤......

  1. 在portal.azure.com中......

    • Azure Active Directory>应用程序注册>新应用程序注册(您可以稍后删除)
    • 为应用程序命名并将其设置为"Wep app/API"
    • 将"登录网址"设置为"https:// blabla"之类的任意内容
    • 转到新创建的应用程序注册并复制"应用程序ID"
  2. 使用Visual Studio 2017创建ASP.NET Core 2.0项目15.4.2 ...

    • ASP.NET核心Web应用程序
    • .NET Framework,ASP.NET Core 2.0,"Web应用程序"
    • 更改身份验证>'工作或学校帐户'
    • 选择'云 - 单一组织'
    • 输入您的域名' something .onmicrosoft.com'(我猜)
    • 单击向导以创建项目
    • 编辑appsettings.json并将'ClientId'更改为'Application ID'(从portal.azure.com复制)
    • 复制为'CallbackPath'设置的值(例如'/ signin-oidc')
    • 转到项目属性>调试>并复制IIS Express https URL(例如'https:// localhost:44366 /')
    • 切换回portal.azure.com中的新App注册
    • "回复网址">从上述两条信息的串联中添加新回复网址(例如"https:// localhost:44366/signin-oidc")
    • 点击"保存"
    • 在Visual Studio中运行该项目
    • 使用Azure Active Directory帐户登录(系统会要求您同意应用程序所需的权限)
    • 然后,您应该最终进入ASP.NET Core演示页面

我不太确定这里......

(我借用模板生成的解决方案中的代码,将"身份验证选项"设置为"个人用户帐户">"在应用内存储用户帐户".)

  • 添加nuget包Microsoft.AspNetCore.Identity.EntityFrameworkCore(我必须首先将Microsoft.AspNetCore.Authentication.Cookies从2.0.0升级到2.0.1,但要安装)
  • 添加nuget包Microsoft.EntityFrameworkCore.SqlServer
  • 添加以下类

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<AspNetCoreIdentity.Data.ApplicationDbContext> options) : base(options)
        {
        }
    
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
        }
    }
    
    public class ApplicationUser : IdentityUser
    {
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 在Startup.ConfigureServices()的开头添加以下内容

    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
    
    Run Code Online (Sandbox Code Playgroud)
  • 将连接字符串添加到appsettings.json(假定localhost上的默认SQL Server实例和名为'AspNetCoreIdentity'的标识数据库)

    "ConnectionStrings": {
      "DefaultConnection": "Data Source=.\\;Initial Catalog=AspNetCoreIdentity;Integrated Security=True;MultipleActiveResultSets=True"
    }
    
    Run Code Online (Sandbox Code Playgroud)

现在,当我再次运行应用程序时,我最终进入了一个重定向循环,我认为在我的应用程序和Azure Active Directory之间运行.追踪节目......

Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Information: Authorization failed for user: (null). Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker: Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.

然后我尝试将方法添加到AccountController(Login,ExternalLogin),希望我可以打破断点,但现在我真的卡住了.

其他参考......

小智 2

我认为我可以做到这一点,但我对这个框架还很陌生,因此欢迎对此方法提出批评。

在启动时,我必须向 Microsoft 的示例添加两件事。

  1. 将DefaultSignInScheme值设置为AuthenticationProperties,以防止授权失败时出现 Stackoverflow 异常(请参阅此处)。
  2. 将访问拒绝路径添加到应用程序 cookie

启动.cs:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddAzureAd(options => Configuration.Bind("AzureAd", options))
        .AddCookie(options =>
        {
            options.AccessDeniedPath = "/AccessDenied";
        });
   // Remaining code removed
Run Code Online (Sandbox Code Playgroud)

然后,我扩展了AzureAdAuthenticationBuilderExtensions >配置AzureOptions类,并在令牌验证事件发生时执行一些额外的工作(即从角色存储中加载用户角色)

AzureAdAuthenticationBuilderExtensions.cs

public void Configure(string name, OpenIdConnectOptions options)
        {
            options.ClientId = _azureOptions.ClientId;
            options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}";
            options.UseTokenLifetime = true;
            options.CallbackPath = _azureOptions.CallbackPath;
            options.RequireHttpsMetadata = false;

            options.Events = new OpenIdConnectEvents
            {                    
                OnTokenValidated = (context) =>
                {                           
                    // Load roles from role store here
                    var roles = new List<string>() { "Admin" };
                    var claims = new List<Claim>();
                    foreach (var role in roles) claims.Add(new Claim(ClaimTypes.Role, role));

                    var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                    context.Principal.AddIdentity(claimsIdentity);

                    return Task.CompletedTask;       
                }                    
            };
        }
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

2017 次

最近记录:

8 年,5 月 前