In ASP.NET Core 2 logging in to Azure AD is fairly easy, in ConfigureServices(IServiceCollection services) just add the following
// Azure AD login
services.AddAuthentication(a =>
{
a.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
a.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
a.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(o => o.LoginPath = new PathString("/Account/SignIn"))
.AddOpenIdConnect(o =>
{
o.ClientId = Configuration["Authentication:AzureAd:ClientId"];
o.ClientSecret = Configuration["Authentication:AzureAd:ClientSecret"];
o.Authority = Configuration["Authentication:AzureAd:AADInstance"] +
Configuration["Authentication:AzureAd:TenantId"];
o.CallbackPath = Configuration["Authentication:AzureAd:CallbackPath"];
o.ResponseType = OpenIdConnectResponseType.CodeIdToken;
o.Events = new OpenIdConnectEvents
{
OnRemoteFailure = RemoteFailure,
OnTokenValidated = TokenValidated
};
});
and everything works fine. Then I can add Claims in TokenValidated and that works fine aswell:
private Task TokenValidated(TokenValidatedContext context)
{
var claims = new List<Claim>();
var claim = new Claim(ClaimTypes.Role, "Test", ClaimValueTypes.String, "Issuername")
context.Principal.AddIdentity(new ClaimsIdentity(claims));
return Task.FromResult(0);
}
However, it's never quite that easy. The Claims I want are dependent on a external calls to a service, and the address is stored in the configuration.
In ConfigureServices I also have various classes added for dependency injection with works fine for the controllers.
services.AddTransient<IRoleClaims, RoleClaims>();
This RoleClaims is a class I want to call from the TokenValidated method, but as far as I can see I cannot use DI here. Nor can I access the ServiceCollection to get it via ActivatorUtilities.CreateInstance.
The constructor to RoleClaims looks like this:
public RoleClaims(IOptions<EmployeeConfiguration> configuration)
So, the big question: How is this supposed to work? Can I somehow use dependency injection in the TokenValidated method? Am I trying to add my own claims in the wrong place?
In ASP.NET Core 2.0, you can get a service from the contain using:
private async Task TokenValidated(TokenValidatedContext context)
{
var widget = ctx.HttpContext.RequestServices.GetRequiredService<Widget>();
...
}