Search code examples
c#.netpowershellhttplistener

Using NET.HTTPListener in Powershell


I've been using PoSHServer (http://poshserver.net/) for a website that serves some reports, which is working flawlessly. Now I'd like to extend the website's capability to some minor API functionality, but since I'm using authentication for the server, it doesn't really work as expected.

The server is using .NET's HTTPListener and the documentation obviously only shows C# examples.

To achieve what I want, the documentation from Microsoft shows that I should set the AuthenticationDelegate before starting the listener, as seen below:

// Specify the authentication delegate.

listener.AuthenticationSchemeSelectorDelegate = 
new AuthenticationSchemeSelector (AuthenticationSchemeForClient);

And the method from the above should be defined as such:

static AuthenticationSchemes AuthenticationSchemeForClient(HttpListenerRequest request)
{
    Console.WriteLine("Client authentication protocol selection in progress...");
    // Do not authenticate local machine requests.
    if (request.RemoteEndPoint.Address.Equals (IPAddress.Loopback))
    {
        return AuthenticationSchemes.None;
    }
    else
    {
        return AuthenticationSchemes.IntegratedWindowsAuthentication;
    }
}

However, I'm having trouble converting this to Powershell - I hope someone can assist me on this.

Documentation is from here: https://learn.microsoft.com/en-us/dotnet/api/system.net.authenticationschemeselector?view=net-6.0


Solution

  • EDIT

    While looking at bit more at the documentation, I noticed that the delegate supports a bitwise combination of its member values.

    Therefore, a solution entirely in Powershell is possible.

    Here's my take on it, switching based on /api/ in url and firefox as useragent:

    $Listener.AuthenticationSchemeSelectorDelegate = {param($request) 
     if ($request.RawUrl.StartsWith("/api/")) {
       return 32768 #AuthenticationSchemes.Anonymous
     } elseif ($request.UserAgent.Contains("Firefox")) {
       return 8 #AuthenticationSchemes.Basic
     } else {
       return 6 #AuthenticationSchemes.IntegratedWindowsAuthentication
     }
    }
    

    The bit values are from the 'AuthenticationScheme Enum' documentation: https://learn.microsoft.com/en-us/dotnet/api/system.net.authenticationschemes?view=net-6.0

    Hopefully someone else using .NET HttpListener in Powershell might benefit.

    Old solution compiling C# and adding as a Type

    For anyone looking for the answer, I found it from this Reddit thread: https://www.reddit.com/r/PowerShell/comments/gob334/help_assigning_delegate_to_http_listener/

    This is my variation of it, that allows anonymous when the endpoints URL is "/api/", and to change to basic auth when Firefox browser is used:

    Add-Type -Language CSharp -TypeDefinition @"
      using System.Net;
      public class AuthProvider {
       public static AuthenticationSchemeSelector AuthSelector() {
         return delegate (HttpListenerRequest request) {
              if (request.RawUrl.StartsWith("/api/")) return AuthenticationSchemes.Anonymous;
              else if (request.UserAgent.Contains("Firefox")) return AuthenticationSchemes.Basic;
              else return AuthenticationSchemes.IntegratedWindowsAuthentication;
              };
           }
        }
    "@
    
    $Listener.AuthenticationSchemeSelectorDelegate = [AuthProvider]::AuthSelector()