1

I am trying to build the ASP.NET Core Web API from this link (https://learn.microsoft.com/en-us/azure/notification-hubs/push-notifications-android-specific-users-firebase-cloud-messaging). It wants me to register the MessageHandler using the following code:

config.MessageHandlers.Add(new AuthenticationTestHandler());

It says to "add the following code at the end of the Register method in the Program.cs file. There is no register method in the Program.cs file. Everything I have found indicates that the Register method is part of a class called WebApiConfig, but I don't have one of those either, and when I create one, it cannot find HttpConfiguration. How do I register the MessageHandler?

ServerS
  • 452
  • 3
  • 15
  • This documentation page looks wrong to me. It says "Create the new **ASP.NET Core 6.0** web API". But the rest of the tutorial has not been adjusted for ASP.NET Core. E.g. in `AuthenticationTestHandler` they use `HttpContext.Current.User` which is from old ASP.NET Framework. I would send feedback to Microsoft using the button at the bottom of the page. – Dimitris Maragkos Sep 03 '22 at 21:20
  • @DimitrisMaragkos I believe this is correct. I think I have successfully changed the rest of the code to be for ASP.NET Core, but I cannot figure this one thing out. – ServerS Sep 03 '22 at 21:26

1 Answers1

2

In ASP.NET Core the equivalent to a MessageHandler is middleware. I converted AuthenticationTestHandler to middleware:

AuthenticationTestMiddleware.cs:

public class AuthenticationTestMiddleware
{
    private readonly RequestDelegate _next;

    public AuthenticationTestMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var authorizationHeader = context.Request.Headers["Authorization"].FirstOrDefault();

        if (authorizationHeader != null && authorizationHeader
            .StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase))
        {
            string authorizationUserAndPwdBase64 =
                authorizationHeader.Substring("Basic ".Length);
            string authorizationUserAndPwd = Encoding.Default
                .GetString(Convert.FromBase64String(authorizationUserAndPwdBase64));
            string user = authorizationUserAndPwd.Split(':')[0];
            string password = authorizationUserAndPwd.Split(':')[1];

            if (VerifyUserAndPwd(user, password))
            {
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, user)
                };

                var claimsIdentity = new ClaimsIdentity(
                    claims: claims,
                    authenticationType: "password");

                context.User.AddIdentity(claimsIdentity);
                await _next(context);
            }
            else
            {
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
            }
        }
        else
        {
            context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
        }
    }

    private bool VerifyUserAndPwd(string user, string password)
    {
        // This is not a real authentication scheme.
        return user == password;
    }
}

Now in Program.cs you can register like this:

app.UseMiddleware<AuthenticationTestMiddleware>();

Questions I found regarding converting MessageHandler to middleware:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/write?view=aspnetcore-6.0

Edit:

Found an official sample that is updated for ASP.NET Core:

https://github.com/Azure/azure-notificationhubs-dotnet/tree/main/Samples/WebApiSample/WebApiSample

Dimitris Maragkos
  • 8,932
  • 2
  • 8
  • 26
  • Thanks. I still don't see how to make the controllers interact with the Middleware. From debugging it, it seems that the middleware is not running. I've added both app.UseMiddleware(); as well as builder.Services.AddTransient(); – ServerS Sep 05 '22 at 14:35
  • Can you share the code of your `Program.cs` – Dimitris Maragkos Sep 05 '22 at 15:25
  • using AppBackend; using Microsoft.Extensions.Http; using System.Reflection; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddHttpContextAccessor(); builder.Services.AddTransient(); var app = builder.Build(); app.UseMiddleware(); // Configure the HTTP request pipeline. app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); – ServerS Sep 05 '22 at 16:08
  • `builder.Services.AddTransient();` is not needed. Apart from that it should be working fine. When you make a request to any endpoint on the app you should be getting 403 forbidden response unless the request has a valid Authorization header. – Dimitris Maragkos Sep 05 '22 at 16:22
  • Interesting. I get 200 OK response on everything, but it is not working correctly. – ServerS Sep 05 '22 at 16:25
  • How did you test? The documentation has a demo android app with a log in button. If you put same username password (Jim, Jim) you should get 200 ok response. If you put different username than password you should get forbidden. The android app has `sendPush` method which makes an http request to the web api. Do you get 200 ok on this request even you put different username and password? – Dimitris Maragkos Sep 05 '22 at 16:34
  • I do get 403 with a different password and 200 when user and password are the same. So I guess it is running. The issue seems to be that the username is not getting transferred into the RegisterController so that it can register the device using the username as a tag. – ServerS Sep 05 '22 at 17:04
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/247797/discussion-between-dimitris-maragkos-and-servers). – Dimitris Maragkos Sep 05 '22 at 17:25