DI in AuthorizationRequirement
Brandon2255p opened this issue · comments
I am struggling to figure out how to inject into an AuthorizationRequirement
I am trying to inject IClient in the following code example.
When setting up the policy, I have to use a constructor which means I am not using DI
_.AddPolicy(GraphQLPolicyNames.HomeAccess, policy =>
{
policy.AddRequirement(new BasicAccessRequirement());
policy.AddRequirement(new HomeAccessRequirement());
});
public class HomeAccessRequirement : IAuthorizationRequirement
{
private readonly IClient client;
public HomeAccessRequirement(IClient client)
{
this.client = client;
}
public Task Authorize(AuthorizationContext context)
{
if (AuthorizationHelpers.IsAdminOrSuperAdmin(context.User))
{
return Task.FromResult(0);
}
var hasId = context.InputVariables.ContainsKey("Id");
if (hasId)
{
dynamic id;
context.InputVariables.TryGetValue("Id", out id);
var home = client.GetData(id);
}
return Task.FromResult(0);
}
}
How can I achieve DI to inject the IClient which is needed for authorization
Unfortunately there is no such possibility.
Instead of making IAuthorizationRequirement
DI-dependent, use in as simple class to hold requirement-related information.
And then create a DI-dependent handler (HomeAccessHandler : AuthorizationHandler<HomeAccessRequirement>
) to process the requirement.
This should help you.
P.S. Note the "Handler registration" section.
This is core auth package, for ASP.NET Core other one exists.
@Brandon2255p how about that?
services.AddGraphQLAuth((_, s) =>
{
_.AddPolicy(GraphQLPolicyNames.HomeAccess, policy =>
{
policy.AddRequirement(s.GetRequiredService<BasicAccessRequirement>());
policy.AddRequirement(s.GetRequiredService<HomeAccessRequirement>());
});
};
You should of cource configure your requirements in DI-container.
Closed due to lack of feedback.
i tried your solution @sungam3r for a similar issue i'm having but i get System.InvalidOperationException: 'No service for type 'CoreAPI.HomeAccessRequirement' has been registered.'
services.AddSingleton<IAuthorizationRequirement>(x => new HomeAccessRequirement(x.GetRequiredService<IClient>()) );
`services.AddGraphQLAuth((_, s) =>
{
_.AddPolicy("UserRolePolicy", p => p.AddRequirement(s.GetRequiredService<HomeAccessRequirement>()));
});`
the above did not work, I am relatively new to C# is my error glaringly obvious?
AddGraphQLAuth
is not a part of this project (maybe it is in the server project?), but for using DI it should look closer to this:
services.AddSingleton<HomeAccessRequirement>();
services.AddGraphQLAuth((_, s) =>
{
_.AddPolicy("UserRolePolicy", p => p.AddRequirement(s.GetRequiredService<HomeAccessRequirement>()));
});
If you register HomeAccessRequirement
as IAuthorizationRequirement
, then DI does not have a registration of HomeAccessRequirement
, only IAuthorizationRequirement
.
Also just noticed that you may be referencing #54 (comment) for that extension.
thanks joe, not exactly what i was looking for as i have another service that needs to be injected into HomeAccessRequirement and the above did not work. I am attempting the other route which is to make my injected service available to httpcontextaccessor
If you have another service that needs to be injected, that other service just needs to be also registered with DI. If it doesn't work this way, then it won't work the other way either.
services.AddTransient<HomeAccessRequirement>();
services.AddTransient<IClient, MyClient>();
public class HomeAccessRequirement : IAuthorizationRequirement
{
private readonly IClient client;
public HomeAccessRequirement(IClient client)
{
this.client = client;
}
public Task Authorize(AuthorizationContext context)
{
...
}
}
services.AddGraphQLAuth((_, s) =>
{
_.AddPolicy("UserRolePolicy", p => p.AddRequirement(s.GetRequiredService<HomeAccessRequirement>()));
});
thanks! @joemcbride i have been going in circles over and over with this. Seems like I need to look into why I can't dependency inject this...
@mmmikeal Here's a full working example that uses injection in a IAuthorizationRequirement
.