首页 > 解决方案 > Understanding scoping issues using ClaimsTransformation and DI for access to dbContext

问题描述

Currently, I am attempting to implement ClaimsTransformation inside my OnTokenValidated event and I am getting scoping issues. The error I receive is:

System.InvalidOperationException: Cannot consume scoped service 'Microsoft.AspNetCore.Authentication.IClaimsTransformation' from singleton 'Microsoft.Extensions.Options.IConfigureOptions`1[Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions]'.

First, here's the registration of my services.

services.AddAuthentication(sharedOptions =>
{
    sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAd(options => Configuration.Bind("AzureAd", options))
.AddCookie
    (cookie =>
    { 
        cookie.AccessDeniedPath = "/Error";
    });

// This sample uses an in-memory cache for tokens and subscriptions.
services.AddMemoryCache();
services.AddSession();

// Add application services.
//services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton<IGraphAuthProvider, GraphAuthProvider>();
services.AddTransient<IGraphSdkHelper, GraphSdkHelper>();

// DI for claims transformation
services.AddTransient<IClaimsTransformation, ClaimsTransformer>();

// DEBUG DB (local)
services.AddDbContext<TestContext>(options =>
 options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TestContext;Trusted_Connection=True;MultipleActiveResultSets=true"));

Next, I register additional services inside my AuthenticationBuilder.

public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
{
    builder.Services.Configure(configureOptions);
    builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>();
    builder.AddOpenIdConnect();
    return builder;
}

Within my AzureAdAuthenticationBuilderExtensions file where I host the OpenIdConnectResponseType events, I pass in the claims principal.

},OnTokenValidated = async (context) =>
{
    // Pass in the claims principal to append ACLs
    await _claimsTransformer.TransformAsync(context.Principal);
}

And here is the snippet where I attempt to access my dbContext through DI which causes the scoping issues.

private readonly Test.Models.TestContext _dbContext;

public ClaimsTransformer(TestContext dbContext)
{
    _dbContext = dbContext;
}

I understand the overall issue of a service depending on another service with a shorter lifespan, however, I have followed several different resources online to cobble this implementation together and I'm not quite sure how to resolve the issue and allow access to my dbContext service within my ClaimsTransformation implementation. I did see entirely different solutions that didn't use claimstransformation at all and instead elected to use a UserClaimsPrincipalFactory though I don't know if that's just an alternative or is, in fact, the current encouraged way to implement this functionality.

https://kevin-junghans.blogspot.com/2017/08/customizing-claims-for-authorization-in.html

Also, any critiques to code and/or concerns are always welcome, I always appreciate an opportunity to learn! As an addendum, I am working with AzureAD but do not have the capability to create groups within this Azure instance and so I am planning on creating user entries in my DB and storing their associated roles for use in authorization in my application. Hence the need to append a new claim to the principal once a user authenticates and the need to perform a lookup in my DB to see what roles the user should have.

标签: azure-active-directoryasp.net-core-2.0claims-based-identity

解决方案


推荐阅读