Translate ninject ISecureDataFormat binding to Autofac
Asked Answered
T

2

50

I am migrating a large codebase from Ninject to Autofac and am struggling on one of the bindings that I believe is causing an activation error based on some of my debugging.

Ninject:

Bind<ISecureDataFormat<AuthenticationTicket>>()
     .ToMethod(context =>
         {
             var owinContext = context.Kernel.Get<IOwinContext>();
             return owinContext
                    .Get<ISecureDataFormat<AuthenticationTicket>>("SecureDataFormat");
         });

Autofac (what I have):

builder.Register(
    context => context.Resolve<IOwinContext>()
        .Get<ISecureDataFormat<AuthenticationTicket>>("SecureDataFormat"))
        .As<ISecureDataFormat<AuthenticationTicket>>();

Startup.cs:

var container = RegisterIoC(app, config);

public IContainer RegisterIoC(IAppBuilder app, HttpConfiguration config)
    {
        var builder = new ContainerBuilder();
        builder = RegisterDependencies(builder);
        builder = RegisterFilters(builder, config);

        /*builder.RegisterModule<DebuggingRequestModule>();*/

        var container = builder.Build();

        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

        app.UseAutofacMiddleware(container);
        app.UseAutofacMvc();
        app.UseAutofacWebApi(config);
        app.UseWebApi(config);

        return container;
    }

More:

builder.RegisterModule<ApiDependencyModule>().RegisterModule<AutofacWebTypesModule>();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(typeof(AccountController).Assembly);

(seemingly) associated constructors:

AccountController.cs:

public AccountController(ILoginService loginService,
                             IBearerTokenStore tokenStore,
                             IRememberMeCookieService rememberMeCookieService,
                             IInternalSsoChallenge ssoChallenge)
{
}

LoginService.cs:

public LoginService(IBearerTokenStore tokenStore, 
        IGrantTypeProvider grantProvider, 
        IRememberMeCookieService rememberMeCookieService)
{
}

BearerTokenCookieStore.cs:

public BearerTokenCookieStore(IOwinContext owinContext, ISecureDataFormat<AuthenticationTicket> secureDataFormat, IAppSettingsReader appSettingsReader, ICookieService cookieService)
{
}

I have a logging module that is helping me debug, and this is the message list I have:

Resolving  _______.Login.Controllers.AccountController
--Resolving  _______.ApiGateway.Services.Auth.LoginService
----Resolving  _______.ApiGateway.Security.OAuth.BearerTokenCookieStore
------Resolving  Microsoft.Owin.Security.DataHandler.SecureDataFormat`1[Microsoft.Owin.Security.AuthenticationTicket]
Exception thrown: 'Autofac.Core.DependencyResolutionException' in Autofac.dll
Exception thrown: 'Autofac.Core.DependencyResolutionException' in Autofac.dll
Exception thrown: 'Autofac.Core.DependencyResolutionException' in Autofac.dll
The thread 0x1014 has exited with code 0 (0x0).

Edit:

The exception I am seeing:

An error occurred during the activation of a particular registration.
See the inner exception for details. Registration: 
Activator = AccountController (DelegateActivator), 
Services = [____.Login.Controllers.AccountController], 
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, 
Sharing = None, 
Ownership = ExternallyOwned ---> 
An error occurred during the activation of a particular registration. 
See the inner exception for details. 
Registration: 
Activator = AccountController (ReflectionActivator), 
Services = [____.Login.Controllers.AccountController], 
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, 
Sharing = None, Ownership = OwnedByLifetimeScope ---> An error occurred during the activation of a particular registration. 
See the inner exception for details. 
Registration: 
Activator = LoginService (DelegateActivator), 
    Services = [____.ApiGateway.Services.Auth.ILoginService],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,
Sharing = None,
Ownership = ExternallyOwned ---> An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = LoginService (ReflectionActivator),
Services = [____.ApiGateway.Services.Auth.ILoginService],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,
Sharing = None,
Ownership = OwnedByLifetimeScope ---> An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = BearerTokenCookieStore (DelegateActivator),
Services = [____.ApiGateway.Security.OAuth.IBearerTokenStore],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,
Sharing = None,
Ownership = ExternallyOwned ---> An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = BearerTokenCookieStore (ReflectionActivator),
Services = [____.ApiGateway.Security.OAuth.IBearerTokenStore],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,
Sharing = Shared,
Ownership = OwnedByLifetimeScope ---> An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = ISecureDataFormat`1 (DelegateActivator),
Services = [Microsoft.Owin.Security.ISecureDataFormat`1[[Microsoft.Owin.Security.AuthenticationTicket,
Microsoft.Owin.Security,
Version=3.0.1.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35]]],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,
Sharing = None,
Ownership = ExternallyOwned ---> An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = ISecureDataFormat`1 (DelegateActivator),
Services = [Microsoft.Owin.Security.ISecureDataFormat`1[[Microsoft.Owin.Security.AuthenticationTicket,
Microsoft.Owin.Security,
Version=3.0.1.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35]]],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,
Sharing = None,
Ownership = OwnedByLifetimeScope ---> A delegate registered to create instances of 'Microsoft.Owin.Security.ISecureDataFormat`1[Microsoft.Owin.Security.AuthenticationTicket]' returned null. (See inner exception for details.) (See inner exception for details.) (See inner exception for details.) (See inner exception for details.) (See inner exception for details.) (See inner exception for details.) (See inner exception for details.) (See inner exception for details.)

Inner most:

A delegate registered to create instances of 'Microsoft.Owin.Security.ISecureDataFormat`1[Microsoft.Owin.Security.AuthenticationTicket]' returned null.
Transfinite answered 28/3, 2018 at 13:56 Comment(8)
I did include that, both the ninject setup that used to work and the autofac one that is failing in the question.Guiscard
can you add your startup? are you using autofac for owin? did you add app.UseAutofac(container)?Ethical
@Mutmatt - can you include also your packages.xml (it is sufficient to include just owin/webapi/mvc/autofac dependencies). The thing that seems odd in startup is mixing MVC4-like bootstrapping with newer bootstrapping.Rhinitis
We don't have a packages.xml file....Guiscard
@Mutmatt - if not packages (which I recommend - nuget is great ;)) than for sure you have project file - i.e. .csproj with list of dependenices and versions - I'm interested in what is external assemblies you reference and what is version of your Owin, AspNet and AutoFac assemblies.Rhinitis
Try to register the OwinContext into your container builder.Register(ctx=>HttpContext.Current.GetOwinContext()).As<IOwinContext>(); Can you also post how does your old Ninject configuration "Bind" the IOwinContext?Disagreeable
Have you tried registering whichever you are using as your ISecureDataFormat implementation as an open generic implementation of Microsoft.Owin.Security.ISecureDataFormat<> autofaccn.readthedocs.io/en/latest/register/…. You'd have to do some digging to work out what the default is for that, unless you're setting it somewhere, e.g. Microsoft.AspNetCore.Authentication. SecureDataFormat<TData>. Or if it's just Microsoft.AspNetCore.Authentication.TicketDataFormat it would just be a basic registration.Crake
Honestly, I should have answered this question while I still had the codebase in my possession. I'd have to find someone who still works at my previous employer to find the solution I ended up with. I believe I changed the structure of the injectionGuiscard
U
1

We can use autofac with those c# owin inversion-of-control (ninject to autofac) like below, genericly

Startup.cs

public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {

            var config = new HttpConfiguration();
            WebApiConfig.Register(config);    

            ConfigureIoC(app, config);
            Components.Config();

            Auth.ConfigureForApi(app);

            app.UseAutofacWebApi(config);
            app.UseCors(CorsOptions.AllowAll);
            app.UseWebApi(config);
            config.EnsureInitialized();
        }

        private void ConfigureIoC(IAppBuilder app, HttpConfiguration config)
        {
            IoC.RegisterModules(
                builder =>
                {
                    builder.Register<IAuthenticationManager>(c => c.Resolve<IOwinContext>().Authentication).InstancePerRequest();
                    builder.Register<IDataProtectionProvider>(c => app.GetDataProtectionProvider()).InstancePerRequest();
                    builder.RegisterApiControllers(typeof(Startup).Assembly).PropertiesAutowired();
                },
                container =>
                {
                    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
                    app.UseAutofacMiddleware(container);

                },
                true
                );
        }

    }

WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

    }
}

Component config:

public static class Components
{
    public static void Config() {
        TypeAdapterConfig.GlobalSettings.AllowImplicitDestinationInheritance = true;
        var registers = new List<IRegister>();
        registers.Add(new DtoMapping());
        registers.Add(new MappingRegistration());
        TypeAdapterConfig.GlobalSettings.Apply(registers);

        ObjectMapper.Current = new MapsterAdapter();
        DbConfiguration.Loaded += DbConfiguration_Loaded;

        var r = new Registrations();
        r.Run();
    }


    private static void DbConfiguration_Loaded(object sender, System.Data.Entity.Infrastructure.DependencyResolution.DbConfigurationLoadedEventArgs e)
    {
        e.ReplaceService<DbProviderServices>((s, k) => System.Data.Entity.SqlServer.SqlProviderServices.Instance);
    }

}

Authentication:

public class Auth
    {
        public static void ConfigureForMvc(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Login"),

                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, UserEntity, int>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentityCallback: (manager, user) =>
                        user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie),
                        getUserIdCallback: (Identity) => Identity.GetUserId<int>())
                }
            });
        }

        public static void ConfigureForApi(IAppBuilder app)
        {
            var OAuthServerOptions = new OAuthAuthorizationServerOptions()
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/oauth2/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(120),
                Provider = new CustomOAuthProvider(),
                AccessTokenFormat = new CustomJwtFormat(ConfigConstants.Issuer)
            };

            app.UseOAuthAuthorizationServer(OAuthServerOptions);

            app.UseJwtBearerAuthentication(
                new JwtBearerAuthenticationOptions
                {
                    AuthenticationMode = AuthenticationMode.Active,
                    AllowedAudiences = new[] { ConfigConstants.AudienceId },
                    IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                    {
                        new SymmetricKeyIssuerSecurityTokenProvider(ConfigConstants.Issuer, ConfigConstants.AudienceSecurityKey)
                    }
                });

        }
    }
Ulster answered 5/6, 2019 at 21:38 Comment(0)
Y
0

Program.cs

builder.Host.ConfigureContainer<ContainerBuilder>(builder => builder.RegisterModule(new AutofacBusinessModule()));

AutoMapperProfil.cs

namespace BusinessKatman.AutoMappers
{
    public class AutoMapperProfil : Profile
    {
        public AutoMapperProfil()
        {
            CreateMap<PageVM, Page>().ReverseMap();
 }
    }
}

Controllers

private readonly IMapper _mapper;
 public AutoIllerManager(IMapper mapper)
        {            
            _mapper = mapper;
        }
 public IActionResult GetPageDetail
{
var p = _mapper.Map<PageVM>(result);

//and

var p = _mapper.Map<Page>(result);

// list

var p = _mapper.Map<List<Page>>(result);
}
Year answered 30/8, 2022 at 11:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.