Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a proxy to another web api with Asp.net core

I'm developing an ASP.Net Core web application where I need to create a kind of "authentication proxy" to another (external) web service.

What I mean by authentication proxy is that I will receive requests through a specific path of my web app and will have to check the headers of those requests for an authentication token that I'll have issued earlier, and then redirect all the requests with the same request string / content to an external web API which my app will authenticate with through HTTP Basic auth.

Here's the whole process in pseudo-code

  • Client requests a token by making a POST to a unique URL that I sent him earlier
  • My app sends him a unique token in response to this POST
  • Client makes a GET request to a specific URL of my app, say /extapi and adds the auth-token in the HTTP header
  • My app gets the request, checks that the auth-token is present and valid
  • My app does the same request to the external web API and authenticates the request using BASIC authentication
  • My app receives the result from the request and sends it back to the client

Here's what I have for now. It seems to be working fine, but I'm wondering if it's really the way this should be done or if there isn't a more elegant or better solution to this? Could that solution create issues in the long run for scaling the application?

[HttpGet] public async Task GetStatement() {     //TODO check for token presence and reject if issue      var queryString = Request.QueryString;     var response = await _httpClient.GetAsync(queryString.Value);     var content = await response.Content.ReadAsStringAsync();      Response.StatusCode = (int)response.StatusCode;     Response.ContentType = response.Content.Headers.ContentType.ToString();     Response.ContentLength = response.Content.Headers.ContentLength;      await Response.WriteAsync(content); }  [HttpPost] public async Task PostStatement() {     using (var streamContent = new StreamContent(Request.Body))     {         //TODO check for token presence and reject if issue          var response = await _httpClient.PostAsync(string.Empty, streamContent);         var content = await response.Content.ReadAsStringAsync();          Response.StatusCode = (int)response.StatusCode;          Response.ContentType = response.Content.Headers.ContentType?.ToString();         Response.ContentLength = response.Content.Headers.ContentLength;          await Response.WriteAsync(content);     } } 

_httpClient being a HttpClient class instantiated somewhere else and being a singleton and with a BaseAddressof http://someexternalapp.com/api/

Also, is there a simpler approach for the token creation / token check than doing it manually?

like image 490
Gimly Avatar asked Feb 02 '17 10:02

Gimly


People also ask

What is reverse proxy server in .NET Core?

A reverse proxy is a special type of proxy server that hides the target server to the client. The client requests a resource to the proxy server which retrieves it from another server and provides it to the client. In this case, the client has no idea that the resource comes from another server.

What is ForwardedHeaders?

ForwardedHeaders. Identifies which forwarders should be processed. See the ForwardedHeaders Enum for the list of fields that apply. Typical values assigned to this property are ForwardedHeaders.

What is proxy in asp net?

A proxy server handles client requests for resources. A proxy can return a requested resource from its cache or forward the request to the server where the resource resides. Proxies can improve network performance by reducing the number of requests sent to remote servers.


2 Answers

If anyone is interested, I took the Microsoft.AspNetCore.Proxy code and made it a little better with middleware.

Check it out here: https://github.com/twitchax/AspNetCore.Proxy. NuGet here: https://www.nuget.org/packages/AspNetCore.Proxy/. Microsoft archived the other one mentioned in this post, and I plan on responding to any issues on this project.

Basically, it makes reverse proxying another web server a lot easier by allowing you to use attributes on methods that take a route with args and compute the proxied address.

[ProxyRoute("api/searchgoogle/{query}")] public static Task<string> SearchGoogleProxy(string query) {     // Get the proxied address.     return Task.FromResult($"https://www.google.com/search?q={query}"); } 
like image 163
twitchax Avatar answered Sep 30 '22 11:09

twitchax


I ended up implementing a proxy middleware inspired by a project in Asp.Net's GitHub.

It basically implements a middleware that reads the request received, creates a copy from it and sends it back to a configured service, reads the response from the service and sends it back to the caller.

like image 43
Gimly Avatar answered Sep 30 '22 12:09

Gimly