Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not support injected BasicAuthenticationEvents #1

Open
marcrocny opened this issue Jan 19, 2018 · 4 comments
Open

Does not support injected BasicAuthenticationEvents #1

marcrocny opened this issue Jan 19, 2018 · 4 comments

Comments

@marcrocny
Copy link

As an alternative to setting OnSignIn directly, it should be possible to inherit BasicAuthenticationEvents and override SignInAsync(), register the new events-type in ConfigureSerivces and set it on AuthenticationSchemeOptions.EventsType. The security infrastructure will inject it to AuthenticationHandler.Events when the sheme's AuthenticationHandler is resolved by dependency injection (see here).

However, BasicAuthenticationHandler short-circuits this functionality by calling Options.Events.SignInAsync(context). It should be just Events.SignInAsync(context)

@djanosik
Copy link
Owner

Thank you! Can you send a PR?

@marcrocny
Copy link
Author

I'd need a day, unless: is there a way to submit a PR directly without forking?

@marcrocny
Copy link
Author

marcrocny commented Jan 19, 2018

To be honest, I'm hesitant because of the lack of tests on the project. This seems like an innocuous change, but with the level of "magic" in aspnet/Security I'd be worried about breaking something else without some regression testing.

I could probably at least create another "sample" project that exercises the feature. If you're okay with reviewing the change against that and the existing example, then that's okay with me.

@primalfear
Copy link

primalfear commented Mar 3, 2018

There is a very "Ugly" hack to get this working.

public static class AuthenticationServices
    {
        public static IServiceCollection AddAuthenticationServices(this IServiceCollection services)
        {
            if (services == null)
                return null;

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();           
            services.AddTransient<IPrincipalProvider, HttpContextPrincipalProvider>();
            services.AddTransient<Authenticator>();


            var provider = services.BuildServiceProvider();
            services.AddAuthentication("Basic")
                .AddBasic(o =>
                {
                    o.Realm = "Sphinx";
                    o.Events = provider.CreateScope().ServiceProvider.GetRequiredService<Authenticator>();
                });

            return services;
        }
    }

public class Authenticator : BasicAuthenticationEvents
    {
        public IRepository Repository { get; }
        public IMemoryCache MemoryCache { get; }

        public Authenticator(IRepository repository) {
            this.Repository = repository ?? throw new ArgumentNullException(nameof(repository));
        }

        public override async Task SignInAsync(BasicSignInContext context) {


            //Check Cache
            var cacheKey = Extensions.CacheExtensions.GenerateCacheKey(context.UserName, context.Password);
            var data = await this.CreateClaimsFor(context);
            if(data == null)
                return;

            var identity = new ClaimsIdentity(data, context.Scheme.Name);
            context.Principal = new ClaimsPrincipal(identity);
        }

        private async Task<Claim[]> CreateClaimsFor(BasicSignInContext context) {
            
            if (!context.UserName.Equals("apikey", StringComparison.InvariantCultureIgnoreCase))
                return null;

            var intergration = await this.Repository.GetByApiKeyAsync(context.Password);
            
            if (intergration == null || intergration.Status != Constants.Integration.Status.Active)
                return null;

            if (intergration.ApiKey != context.Password)
                return null;

            var claims = new[] {
                new Claim("sub", intergration.Uuid.ToString("N")),
                new Claim("name", intergration.Name),
                new Claim("status", intergration.Status),
                new Claim("organisation", intergration.Organisation.Uuid.ToString("N"))
            };

            return claims;
        }
        
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants