Dependency Injection (using SimpleInjector) and OAuthAuthorizationServerProvider

Gillardo picture Gillardo · Sep 23, 2014 · Viewed 7.6k times · Source

New to Dependency Injection, so this is probably a simple matter, but i have tried and cant figure it out, i am using Simple Injector.

I have a WebApi that uses SimpleInjector perfectly fine, now i would like to implement security using OAuth.

To do this i started to follow this tutorial, which is very helpful, but doesnt use Dependancy Injection

http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/

I have my global.asax file looking like this, to setup dependancy injection (working perfect)

protected void Application_Start()
{
    SimpleInjectorConfig.Register();

    GlobalConfiguration.Configure(WebApiConfig.Register);
}

I have created a Startup.Auth.cs file to configure OAuth

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new MyAuthorizationServerProvider() // here is the problem
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(OAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
}

Now as i commented above, MyAuthorizationServerProvider is the problem. it takes a parameter of IUserService which i usually inject. I do not want to empty constructor because my IUserService also injects a repository. Here is the file

public class ApiAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    private IUserService _service;
    public ApiAuthorizationServerProvider (IUserService service) 
    {
         _service = service;
    }

    public override async Task ValidateClientAuthentication(
        OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    public override async Task GrantResourceOwnerCredentials(
        OAuthGrantResourceOwnerCredentialsContext context)
    {
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", 
            new[] { "*" });

        IUserService service = Startup.Container.GetInstance<IUserService>();
        User user = _service.Query(e => e.Email.Equals(context.UserName) &&
            e.Password.Equals(context.Password)).FirstOrDefault();

        if (user == null)
        {
            context.SetError("invalid_grant", 
                "The user name or password is incorrect.");
            return;
        }

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("sub", context.UserName));
        identity.AddClaim(new Claim("role", "user"));

        context.Validated(identity);

    }
}

How can i get this working with Dependency Injection? This must happen quite a lot and must be able to do something to handle it. I am sure its something simple, but i am still learning.

Answer

Ric .Net picture Ric .Net · Sep 25, 2014

I took some time to find out if it would be possible to register OAuthAuthorizationServerOptions in the Owin pipeling using the app.Use() method directly, instead of app.UseOAuthAuthorizationServer() which is just an extension method over app.Use(). app.Use() has an overload where you could register a delegate which you could use to construct the OAuthAuthorizationServerOptions.

Unfortunately this effort hit a dead end, because it seems that even if we'd use a delegate for the construction, this will be most likely only called once by the Owin pipeline which leads to the same result, namely a singleton instance of the OAuthAuthorizationServerOptions and thus all dependencies of this class will be singleton as well.

So the only solution to keep things working as they should be, is to pull a new instance of your UserService every time the GrantResourceOwnerCredentials() method is called.

But to follow the Simple Injector design principles it would be bad design to keep a dependency on the container in the ApiAuthorizationServerProvider class, like the original code shows.

A better way to do this would be to use a factory for the UserService class instead of directly pulling it from the container. The next code shows an example of how you could do this:

First of all, clean out the Application_Start() method in your global.asax file and place all your startup code in the Owin Startup() method. The code of the Startup() method:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var container = SimpleInjectorConfig.Register();

        GlobalConfiguration.Configure(WebApiConfig.Register);

        Func<IUserService> userServiceFactory = () => 
              container.GetInstance<IUserService>();

        var OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new ApiAuthorizationServerProvider(userServiceFactory)
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(OAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
}

Notice how I changed the signature of the SimpleInjectorConfig.Register() function by returning the completly configured Simple Injector container to the caller so it can be used directly.

Now change the constructor of your ApiAuthorizationServerProvider class, so the factory method can be injected:

public class ApiAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    private Func<IUserService> userServiceFactory;

    public ApiAuthorizationServerProvider(Func<IUserService> userServiceFactory)
    {
        this.userServiceFactory = userServiceFactory;
    }

    // other code deleted for brevity...

    private IUserService userService 
    { 
        get
        {
            return this.userServiceFactory.Invoke();
        }
    }

    public override async Task GrantResourceOwnerCredentials(
        OAuthGrantResourceOwnerCredentialsContext context)
    {
        // other code deleted for brevity...
        // Just use the service like this
        User user = this.userService.Query(e => e.Email.Equals(context.UserName) &&
            e.Password.Equals(context.Password)).FirstOrDefault();

        // other code deleted for brevity...
    }
}

This way you get a new UserService everytime the GrantResourceOwnerCredentials() method is called and the complete dependency graph behind the UserService class will follow the lifetimes you defined in your Simple Injector configuration, while you depend on the container only in the composition root of the application.