Skip to content
Library to manage timing out of authentication failures.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


This project is for managing a binary exponential back off for timeing out logins to a web site. It can probably be used for other uses and is extensable in the delay function by implementing a custom ITimeOutCalculator and passing it to the BackOffTracker.

I was working on an API and wanted to do some exponential lock outs but did not find a library out there so ended up writing this in my spare time.

Getting started

To add BackOffTracker to the project, add a distributed cache manager and then call AddBackOff()

public void ConfigureServices(IServiceCollection services)
    //Adding a caching provider, in this case Microsoft.Extensions.Caching.Distributed.MemoryDistributedCache

    // Other service configuration.

Example in a validation method

OnValidateCredentials = async context =>
        var backOff = context.HttpContext.RequestServices.GetService<IBackOffTracker>();

        //Configure your tracking key as needed
        var key = $"{context.IpAddr}-{context.ApiKey}"

            //Return a failure response

        //Some more advanced validation in prod of course.
        var success = context.ApiKey == "abc123"

        if (success)
            context.Principal = new
                ClaimsPrincipal(new ClaimsIdentity(new []
                        new Claim("TestClaim", "Test"),

            backOff.RegisterResult(key, success);

            backOff.RegisterResult(key, success);

            context.Fail(new AuthenticationException());

The first check is to see if the tracking key is timed out. CheckTimeout will return a CheckTimeoutResult with IsLockedOut and a timespan with the remaining lockout time. This can be returned to the client or not depending on what the goals are.

Next we validate the API key is correct. If the api key is correct we create our ClaimsPrincipal and register the result. If the authentication failed we register the result passing false for success and set the failure condition.

Final Thoughts

  1. Keep your tracking keys small. On a busy webserver and a small cache size there is the risk that cache space becomes an issue.
  2. Use a fast cache. This makes two calls to the caching server for every request.
    a. Once for the timeout check and once to register the result.
    b. I have been thinking about adding a second layer of in memory caching for the time between the first and second cache hits. Im not sure if thats necessary or not yet.

Framework versions supported

Currently this only supports .net Standard 2.0 an on.

You can’t perform that action at this time.