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.