Skip to content

Authentication Events

Hugo Biarge edited this page Feb 3, 2019 · 9 revisions

Starting in version 2.0.0 we have introduced a custom events class that expose four different events that can help you to understand how this thing works or customize advanced usage scenarios.

You can use these events in the standard way:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(TestServerDefaults.AuthenticationScheme)
        .AddTestServer(options =>
        {
            options.Events = new TestServerEvents
            {
                OnMessageReceived = context => Task.CompletedTask,
                OnTokenValidated = context => Task.CompletedTask,
                OnAuthenticationFailed = context => Task.CompletedTask,
                OnChallenge = context => Task.CompletedTask
            };
        })

    var mvcCoreBuilder = services.AddMvcCore()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    ApiConfiguration.ConfigureCoreMvc(mvcCoreBuilder);
        }

OnMessageReceived

The handler raises this event when it receives a new request to be authenticated, but any processing operation has been started yet.

By default, the TestServer sends the claims information from the test in a custom request header. Something like this:

Header name: X-TestServerAuthentication-{scheme}
Header value: {scheme} [serialized data]

In this event you have the chance to access the full authentication context with two main purposes:

  • Set the Token value of the context from other source. For example, you send a custom header with a value that identify a serialized AuthenticationTicket in a database. You can set context.Ticket = "Your serialized ticket" instead of use the .WithIdentity extension methods.
    .AddTestServer(options =>
    {
        options.Events = new TestServerEvents
        {
            OnMessageReceived = context =>
            {
                string ticketId = context.Request.Headers["X-Custom-Header"];
                                                      
                context.Token = myTicketProvider.GetSerializedTokenFromId(ticketId);

                return Task.CompletedTask;
            }
        };
    });
  • Completely bypass the handler and call the Success, Fail or NoResult methods in the event. In this case, the handler will use the authentication context result.
    .AddTestServer(options =>
    {
        options.Events = new TestServerEvents
        {
            OnMessageReceived = context =>
            {
                string principalId = context.Request.Headers["X-Custom-Header"];
                                                       
                context.Principal = myPrincipalProvider.GetPrincipalFromId(principalId);
                            
                context.Success(); // Will produce a success authentication

                return Task.CompletedTask;
            }
        };
    });

OnTokenValidated

The handler raises this event when the token has been located, validated and a new ClaimsPrincipal has been created. The handler will succeed the authentication at this point, but you have the chance to perform additional actions over the created principal (if you want to do any claim transformation remember that you can register your own IClaimsTransformation in the IServiceCollection).

As in the previous event, you can completely bypass the handler and call the Success, Fail or NoResult methods in the event and it will be honored.

OnAuthenticationFailed

The handler raises this event when the authentication has failed (for example an exception has been thrown).

In this event you have the chance to inspect the exception and the rest of the failed authentication context and decide if it is OK to fail the authentication or it is a known exception and you can recover from it and produce a succeed authentication. You can call the Success method in this event and produce a valid authentication result.

OnChallenge

The handler raises this event when a challenge (401) should be sent to the client.

In this event you have the chance to create a custom response and call context.Handled to bypass the default challenge response generated by the handler.