首页 文章

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

提问于
浏览
10

我想创建一个ASP.NET Core 2.0应用程序,它使用Azure Active Directory作为身份提供程序(用于身份验证),但使用ASP.NET Core Identity进行授权(例如使用控制器属性,如'[Authorize(Roles = 921075 )]') . 在解决方案中,我期望本地身份数据库表AspNetUserLogins to hold references to the Azure Active Directory identities

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

My problems:

  • 我可以从Visual Studio解决方案模板中获取Azure Active Directory身份验证,但是我无法弄清楚如何在Startup.ConfigureServices()中的某处添加和配置ASP.NET核心身份(例如services.AddIdentity()等) )

  • 我想知道正确的钩子在哪里进行索赔转换 . (例如OpenIdConnectEvents.OnTokenValidated或者可能是AccountController方法)

Steps to reproduce my baseline...

  • 在portal.azure.com上...

  • Azure Active Directory>应用程序注册>新应用程序注册(稍后可以删除)

  • 为应用程序命名并将其设置为'Wep app / API'

  • 将'Sign-on URL'设为something arbitrary like 'https://blabla'

  • 转到新创建的应用注册并复制'Application ID'

  • 使用Visual Studio 2017创建ASP.NET Core 2.0项目15.4.2 ...

  • ASP.NET核心Web应用程序

  • .NET Framework,ASP.NET Core 2.0,'Web Application'

  • 更改身份验证> 'work or school accounts'

  • 选择'cloud - single organization'

  • 输入您的域名'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注册

  • 'Reply URLs'>从上述两条信息的串联中添加新的回复网址(例如'https://localhost:44366/signin-oidc')

  • 点击'Save'

  • 在Visual Studio中运行项目

  • 使用Azure Active Directory帐户登录(系统会要求您同意应用程序所需的权限)

  • 您应该最终进入ASP.NET Core演示页面

I'm less certain from here...

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

  • 添加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
{
}
  • 在Startup.ConfigureServices()的开头添加以下内容
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();
  • 将连接字符串添加到appsettings.json(假定localhost上的默认SQL Server实例和名为'AspNetCoreIdentity'的标识数据库)
"ConnectionStrings": {
  "DefaultConnection": "Data Source=.\\;Initial Catalog=AspNetCoreIdentity;Integrated Security=True;MultipleActiveResultSets=True"
}

现在当我再次运行应用程序时,我最终进入了一个重定向循环,我认为在我的应用程序和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),希望我可以打一个断点,但现在我真的卡住了 .

其他参考......

1 回答

  • 1

    我认为我有这个工作,但我对这个框架很新,所以对这种方法的批评是值得欢迎的 .

    在启动时,我不得不向微软的例子添加两件事 .

    • 将DefaultSignInScheme值设置为AuthenticationProperties,以防止授权失败时发生Stackoverflow异常(请参阅here) .

    • 将访问被拒绝路径添加到应用程序cookie

    Startup.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
    

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

    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;       
                    }                    
                };
            }
    

相关问题