4

I am trying to figure out .net core dependency injection. My project is currently a web api, with some custom authentication. I've added my authentication like so (in Startups.cs under "ConfigureServices":

services.AddAuthentication(Authentication.Hmac.HmacDefaults.AuthenticationScheme).AddHmac(options =>
                {
                    options.AuthName = "myname";
                    options.CipherStrength = HmacCipherStrength.Hmac256;
                    options.EnableNonce = true;
                    options.RequestTimeLimit = 5;
                    options.PrivateKey = "myprivatekey";
                });

My question is this: How do you access IMemoryCache within the authentication service? I've tried just created a new MemoryCache and passing it in, but that doesn't work. The main goal is for checking Nonce values (see if they are in the cache, if yes auth fails, if no, add to cache auth passes).

Again, this is .NET Core 2 (Web API).

UPDATES:

Here is the basis of the HmacHandler class (the part that ACTUALLY does the auth):

public class HmacHandler : AuthenticationHandler<HmacOptions>
{
private static string Signature;
private static string Nonce;
private static Encoding Encoder { get { return Encoding.UTF8; } set { } }

IMemoryCache MemoryCache { get; set; }

public HmacHandler(IOptionsMonitor<HmacOptions> options, ILoggerFactory logger, UrlEncoder encoder, IDataProtectionProvider dataProtection, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{...}
}

Then there is the "Options" class.

public class HmacOptions : AuthenticationSchemeOptions
{...}

It can't have a constructor that takes parameters. I need to USE the IMemoryCache in the HmacHandler class. I tried adding IMemoryCache to it (in the constructor, etc). That did NOT work.

5
  • I updated the question with some more info. The IMemoryCache needs to be accessed in the "HandleAuthenticateAsync()" method. Again, just for checking to see if a particular nonce has been used within a given amount of time. Commented Sep 23, 2017 at 19:47
  • No error. The cache is always empty. So the nonce (say during a reply attack) is never found in the cache, so it counts as valid. Which leads me to believe that either the cache is "new" with each request..which doesn't make sense. Or the app cache isn't being passed in properly (or something along those lines). Commented Sep 23, 2017 at 19:59
  • In Startup.cs under ConfigureServices I call services.AddMemoryCache(); (before I call app.UseAuthentication....) Commented Sep 23, 2017 at 20:10
  • From what you've said, it seems like all of your DI stuff is set up correctly. I'd now turn your attention to the actual insertion into the cache. Have you confirmed that immediately after setting the item into the cache, it is still there? e.g. with a line to retrieve it back out and log it or inspect it in the debugger? Commented Sep 23, 2017 at 20:19
  • I ended up changing it from "TryGetValue" and "CreateEntry" to "Get" and "Set" for using the cache. Makes me wonder why the others don't work... Commented Sep 23, 2017 at 20:38

4 Answers 4

0

You would need to set IMemoryCache MemoryCache { get; set; } to public if you would like to use outside of the class via dependency injection.

public IMemoryCache MemoryCache { get; set; }
Sign up to request clarification or add additional context in comments.

2 Comments

I switched it to public and same issue. The cache is always empty.
Have you check to confirm that items are making it into the cache?
0

So the answer ended up being a combination of things here. So here is what I did:

  1. Add the "public" to the IMemoryCache in the HmacHandler
  2. Added the IMemoryCache to the constructor of HmacHandler
  3. Changed the get/set of the cache from "TryGetValue/CreateEntry" to pure "Get/Set".

2 Comments

Point #1 would have had no impact: You could simply have a private readonly IMemoryCache _memoryCache; and get the same result.
Good to know this for the future.
0
    private IMemoryCache memoryCache { get; set; }

    public HmacAuthenticationHandler(IOptionsMonitor<HmacAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IMemoryCache memCache)
        : base(options, logger, encoder, clock)
    {
        memoryCache = memCache;
    }

And then in HandleAuthenticateAsync use Get and Set of memoryCache.

Comments

-1
    public void ConfigureServices(IServiceCollection services)
    {                        

        services.AddMemoryCache();
services.AddAuthentication(Authentication.Hmac.HmacDefaults.AuthenticationScheme).AddHmac(options =>
                {
                    options.AuthName = "myname";
                    options.CipherStrength = HmacCipherStrength.Hmac256;
                    options.EnableNonce = true;
                    options.RequestTimeLimit = 5;
                    options.PrivateKey = "myprivatekey";
                    // do your stuff with Test class here
                });

    }
public class Test {
  private IMemoryCache _cache;
  public Test(IMemoryCache cache) {
    _cache = cache;
  }
}

3 Comments

I haven't been able to get that to work. Part of it may be the fact that I'm not 100% familiar with dependency injection/.net core 2. So these are the classes I have inside of the Authentication mechanism. I have the HmacOptions which inherits "AuthenticationSchemeOptions" (this is where I originally wanted it, but it can only do parameterless constructors. I have the HmacHandler which inherits "AuthenticationHandler<HMacOptions>". Those two places don't seem to work. I also tried adding an IMemoryCache component to the HMacHandler's constructor. No go.
I also tried adding an IMemoryCache component to the HMacHandler's constructor. did you tried to do it like singleton
that I did. I tried call it with singleton services.AddSingleton<HmacHandler>(); Didn't work either :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.