Closed Shazwazza closed 7 years ago
I don't think any changes will be necessary to achieve what you want. You can access the IAuthorizationService
instance through the AuthorizationOptions
that you have configured. Get a reference to your AuthorizationOptions
and look at options.Dependencies.Service
. From there, you should be able to use the IAuthorizationService
as you desire. The service will be initialized by default if it has not been overloaded.
There are many ways to get a reference to your AuthorizationOptions
and they all depend upon your specific implementation. If you are using owin and an IoC framework, then I would register the options instance as a singleton in your owin startup, then inject it into your controller. If you are using a more classic asp.net approach, then I would probably create the options in Global.asax and statically hold a reference to it (which would not be ideal due to testability problems, but hey, that's part of why owin became a thing). The key here is that you need to somehow save a reference to your AuthorizationOptions
because then you can access it later in your controller.
Does that solve your issue?
Hi, yup i know i can get a reference to IAuthorizationService from the AuthorizationOptions but those are only available in Owin startup. I need a reference to IAuthorizationService inside of my WebApi controller because I need to manually call:
AuthorizationService.AuthorizeAsync(ClaimsPrincipal, new ContentResourceAccess(id), AuthorizationPolicies.ContentRead);
The important part here is the middle parameter because I need to pass an instance of my resource because this inline authorization policy needs this contextual information which cannot be done using the attribute. For example this is what I'm after: https://docs.microsoft.com/en-us/aspnet/core/security/authorization/resourcebased
However, i am not using IoC so i cannot register IAuthorizationService
in a container and have it injected. I will need to access IAuthorizationService
from the OwinContext (or similar) and there doesn't seem to be a public way to do that. For now, my work around is as follows:
//Need a wrapper to add to the OwinContext which needs to be IDisposable
internal class AuthorizationServiceWrapper : IDisposable
{
public IAuthorizationService AuthorizationService { get; }
public AuthorizationServiceWrapper(IAuthorizationService authorizationService)
{
AuthorizationService = authorizationService;
}
public void Dispose()
{
}
}
//Add this to the OwinContext when configuring my auth policies:
app.CreatePerOwinContext(() => new AuthorizationServiceWrapper(options.Dependencies.Service));
//Then in my controller I can get this wrapper from the OwinContext
var authService = Request.GetOwinContext().Get<AuthorizationServiceWrapper>().AuthorizationService;
I've just seen this reference https://github.com/DavidParks8/Owin-Authorization/issues/53#issuecomment-286955199
So is the preferred way to do this like this instead?
var authorizationService = AuthorizationDependencies.Create(new AuthorizationOptions()).Service;
AuthorizationDependencies.Create
still requires that you have a reference to your AuthorizationOptions
in the controller. I would recommend this instead:
public static class AuthorizationServiceContext
{
public static IAuthorizationService Current { get; set; }
}
and in startup.cs...
AuthorizationServiceContext.Current = options.Dependencies.Service;
This fits the pattern of Asp.net old without dependency injection (like HttpContext.Current
), and it is not coupled to OWIN. This will, however, make testing concurrently very annoying due to race conditions in the Static setter (unless you know how to manipulate the AppDomain
or have already solved this). If you see that as being an issue, then we should consider exposing the IAuthorizationService
via an extension method in the core library such as: Request.GetOwinContext().GetAuthorizationService();
.
Thanks. I think for now i'll stick to my AuthorizationServiceWrapper
work around since that is still easily unit testable and i can just extract the IAuthorizationService
that i referenced from my options in the OwinContext
At any rate, you've identified an easy-to-add extensibility point, and I'll be including the extension in the next release.
Great! :) thanks for your feedback.
A new version has been released with the new extension method.
wow, that was very quick :) cheers!
I can see this class
AuthorizationDependencyHelper
is internal which is used to extract the authorization options and therefore the IAuthorizationService but i can't see a way to get access to the IAuthorizationService inside of a WebApi controller without duplicating this code. I know i can create an instance ofAuthorizationHelper
but that doesn't let me executeAuthorizeAsync
with a resource specified (such asAuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, object resource, AuthorizationPolicy policy)
)Any tips? I can make a PR to update
AuthorizationHelper
to have an overload or publicize AuthorizationDependencyHelper if needed