Using Blazor with a YARP downstream API protected using certificate authentication

This article shows how to use a downstream API protected with certificate authentication using Microsoft YARP reverse proxy from a Blazor application. The Blazor WASM HTTP requests are sent to a secured backend which uses YARP to forward the requests to the API protected with the certificate authentication. The Blazor application authenticates using the OpenIddict identity provider using the BFF security architecture. The downstream API which is protected using the certificate authentication is deployed to an Azure App Service and requires a known client certificate to use the API.

Code https://github.com/damienbod/AspNetCoreOpeniddict

Setup

The application was built using the openiddict-samples and the Dantooine sample. Only small changes to the YARP configuration is required to implement the API calls. The dotnet template Blazor.BFF.OpenIDConnect.Template could also be used to setup the Blazor application. This pre-configures the BFF authentication and uses standard OpenID Connect.

The API protected using certificate authentication is implemented using the following code: AzureCertAuth. This application is deployed to the Azure App service and certificates are required to use the application. The server validates that the correct certificate is used to access the API.

The YARP reverse proxy is setup in the startup class and the app settings. The client certificate required for the downstream API, is loaded into the project using the X509Certificate2 class. This could be loaded from the operating system, or Azure key vault or some other secure way. The demo loads this directly in an unsecure way.

The AddReverseProxy method adds the YARP definitions and the ConfigureHttpClient method is used to add the SslOptions containing the client certificate which is used for the Azure API calls. The MapReverseProxy is used to add the endpoints and reads the configuration from the app settings.

public void ConfigureServices(IServiceCollection services)
{
	// ...

   // Create an authorization policy used by YARP when forwarding requests
   // from the WASM application to the Dantooine.Api1 resource server.
   services.AddAuthorization(options => options.AddPolicy("CookieAuthenticationPolicy", builder =>
   {
      builder.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme);
      builder.RequireAuthenticatedUser();
    }));

	var cert = new X509Certificate2("client.pfx", "1234");

	services.AddReverseProxy()
		 .ConfigureHttpClient((context, handler) =>
		 {
			 handler.SslOptions = new SslClientAuthenticationOptions
			 {
				ClientCertificates = new X509CertificateCollection
				{
					cert
				}
			 };
		 })
		.LoadFromConfig(Configuration.GetSection("ReverseProxy"));
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	// ...
	
	app.UseEndpoints(endpoints =>
	{
		endpoints.MapRazorPages();
		endpoints.MapControllers();
		endpoints.MapReverseProxy();
		endpoints.MapFallbackToPage("/_Host");
	});
}

The ReverseProxy settings adds the configuration which is almost standard like the documentation. The CookieAuthenticationPolicy is used to accept only authenticated requests.

"ReverseProxy": {
	"Routes": {
	  "route1": {
		"ClusterId": "cluster1",
		"AuthorizationPolicy": "CookieAuthenticationPolicy",
		"Match": {
		  "Path": "{**catch-all}"
		}
	  }
	},
	"Clusters": {
	  "cluster1": {
		"HttpClient": {
		  "SslProtocols": [
			"Tls12"
		  ]
		},
		"Destinations": {
		  "cluster1/destination1": {
			"Address": "https://azurecertauth20201108214641.azurewebsites.net/"
		  }
		}
	  }
	}
}

Blazor WASM is used to implement the UI which calls the YARP endpoint. The backend validates the HTTP requests for a secure cookie and a valid session and uses a client certificate to get the data from the Azure API. The Azure API validates the client certificate.

Notes

This works nicely and the downstream APIs can be protected in a secure way. Using this approach, it is very easy to increase security or implement the app to app security in a good way. Of course security is only as good as the weakest link. The WASM UI view calling to the API protected with cookies is now the weakest link, depending of course on how you secure the downstream APIs, but these should not be a problem to do correctly. The API using the YARP reverse proxy uses cookies but has no anti-forgery protection in this demo. This would need to be added.

Links

https://github.com/microsoft/reverse-proxy

https://github.com/damienbod/Blazor.BFF.OpenIDConnect.Template

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth

https://github.com/openiddict/openiddict-samples

https://github.com/damienbod/AspNetCoreCertificates

One comment

  1. […] Using Blazor with a YARP downstream API protected using certificate authentication – Damien Bowden […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: