0

I have an API Gateway, in this instance is called Gateway.Api. Within the Startup class I have the following:

public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddOcelot(Configuration);
        services.AddMvc();

        var appSettingSection = Configuration.GetSection("AppSettings");
        services.Configure<AppSettings>(appSettingSection);

        var appSettings = appSettingSection.Get<AppSettings>();
        var key = Encoding.ASCII.GetBytes(appSettings.Secret);

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.SaveToken = true;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseAuthentication();
        app.UseOcelot().Wait();
        app.UseMvc();
    }

As you can see it defines the authentication scheme.

Using Ocelot I have the following configuration file for my Gateway.Api:

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/customer",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 50366
        }
      ],
      "UpstreamPathTemplate": "/api/customer",
      "UpstreamHttpMethod": [ "Get" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Bearer",
        "AllowedScopes": []
      }
    },
    {
      "DownstreamPathTemplate": "/api/user/authenticate",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 50353
        }
      ],
      "UpstreamPathTemplate": "/api/user/authenticate",
      "UpstreamHttpMethod": [ "Post" ]
    }
  ],
  "GlobalConfiguration": {
    "UseServiceDiscovery": false
  }
}

When I try to access http://localhost:50333/api/customer (Gateway.Api has a port of 50333) without a token I get a 401 response which proves that the configuration file as well as the authentication works.

As well as the Customer microservice, I also have an Identity microservice which allows users to authenticate using a valid username and password which will then issue a token. Using this token to then call the Customer service I get a successful response (200 OK).

Now for some reason, if I access the Customer service directly without using the Gateway (so http://localhost:50366/api/customer) I am able to get a successful response without a token.

Below is the Customer microservice:

[Route("api/[controller]")]
public class CustomerController : Controller
{
    [HttpGet]
    public IEnumerable<string> Get()
    {
        var customers = new string[] {
            "test",
            "test"
        };

        return customers;
    }
}

Does this mean that I have to add an authentication scheme to every microservice Startup class? If so, isn't this overkill?

What I did try is using a [Authorize] attribute on the actions within the Customer microservice however this throws an exception that their is no default authentication scheme.

KTOV
  • 559
  • 3
  • 14
  • 39

2 Answers2

1

This is development environment so you can access the url directly . Your Customer service have no idea of gateway. In actual production environment you generally will only expose API gateway and rest of the services sit behind firewall (private subnet). Only API gateway has access to them. The only way to access the services is to pass through the gateway. If however you want to expose the services publicly then individual service authentication is must.

Regardless It's always good idea to add authentication to services that you want to secure.

Imran Arshad
  • 3,794
  • 2
  • 22
  • 27
  • I understand, however can a user not sniff out the next call from the api endpoint? Although the Customer service is hidden would a user not be able to user fiddler to find what call it makes in the end and see that customer service has no authorization? – KTOV May 13 '19 at 23:44
  • That's not possible. The only way it's possible if your customer service has public endpoint. If Gateway is the only public end point then there is no way a request can pass through. However it's a good idea to put authentication in case some in team accidentally opens the api or mess up with configuration. Sniffing in my opinion is only possible if you are sitting within the environment or data centre. But that too can't access the service if it's behind private subnet. – Imran Arshad May 14 '19 at 00:03
0

Let's understand it this way, why do we use API Gateway?

There are many reasons to use API Gateway and one of them is:

So that we can add authentication at API gateway instead of adding authentication code in many micro services.

In production server machine we open only API Gateway port for end users, user have no idea of where other micros services are hosted nor they can access by trying other ports because other ports are not open!

Also we can put micros services in just another machine which is only accessible to the machine which hosts API Gateway by whitelisting it's IP address.

But In this scenario you are having trust on your developers and DevOps team, else you can put further authentication on high value microservice and this authentication will not be different from the authentication which the end user used, here you will authenticate the API Gateway.

codemirror
  • 3,164
  • 29
  • 42