My statup.cs class code looks like this:
namespace Tenet.eReserve.Api.WebApi
{
public class Startup
{
public IConfiguration Configuration { get; }
public string SuperSecret { get; set; }
public Startup(IConfiguration configuration) => Configuration = configuration;
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddSingleton<IConfiguration>(Configuration);
services.Configure<Settings>(Configuration.GetSection("eReserve"));
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "eReserve API List", Version = "v1" });
c.AddSecurityDefinition("Bearer",
new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme.",
Type = SecuritySchemeType.Http, //We set the scheme type to http since we're using bearer authentication
Scheme = "bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement{
{
new OpenApiSecurityScheme{
Reference = new OpenApiReference{
Id = "Bearer", //The name of the previously defined security scheme.
Type = ReferenceType.SecurityScheme
}
},new List<string>()
}
});
});
services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
}).AddNewtonsoftJson(); // to convert string values to int32 and decimal
services.AddScoped<IReportService, ReportService>();
services.AddScoped<ISearchService, SearchService>();
var sp = services.BuildServiceProvider();
// This will succeed.
var settings = sp.GetService<IOptionsSnapshot<Settings>>();
services.AddApplicationInsightsTelemetry(options =>
{
options.EnableDebugLogger = false;
});
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.WithOrigins(settings.Value.SignalROrigniURL) //http://localhost:8090")
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed((x) => true)
.AllowCredentials());
// options.AddPolicy("CorsPolicy",
// builder => builder.AllowAnyOrigin()
//.AllowAnyMethod()
//.AllowAnyHeader());
});
services.AddAuthentication(opt =>
{
opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(
);
services.ConfigureOptions<ConfigureJwtBearerOptions>();
services.AddHttpContextAccessor();
services.AddAuthorization(options =>
{
options.AddPolicy("HospitalCode", policy =>
policy.Requirements.Add(new HospitalCodeRequirement()));
});
services.AddSingleton<IAuthorizationHandler, FacilityHandler>();
services.AddSignalR(options =>
{
options.EnableDetailedErrors = true;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, TelemetryConfiguration configuration, IOptionsSnapshot<Settings> settings)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAzureAppConfiguration();
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "eReserve API V1");
c.RoutePrefix = String.Empty;
});
configuration.InstrumentationKey = settings.Value.AppInsightsInstrumentationKey;
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthentication(); // this one first
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<NotifyClientService>("/lockNotification");
});
//app.UseSignalR(routes =>
//{
// routes.MapHub<NotifyClientService>("/lockNotification");
//});
}
}
}
And in the angular I am creating a connection like this:
private hubConnection: signalR.HubConnection;
public startConnection = () => {
this.hubConnection = new signalR.HubConnectionBuilder()
.withUrl(this.apiBase + 'lockNotification')
.build();
this.hubConnection
.start()
.then(() => console.log('Connection started'))
.catch(err => console.log('Error while starting connection: ' + err));
}
public startListener = () => {
this.hubConnection.on('LockNotification', (facilityName, lockType, hospitalCode) => {
//logic
}
});
}
This arrangement works locally but when deployed it give CORS error:
Access to fetch at 'https://abc-api.com/lockNotification/negotiate?negotiateVersion=1' from origin 'https://abc-ui.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. zone.js:1118 POST https://xxx-xxx.com/lockNotification/negotiate?negotiateVersion=1 net::ERR_FAILED
Please note that "settings.Value.SignalROrigniURL" return "https://abc-ui.com" (fake url)
UPDATE
In the ConfigureServices method i have Cors like this:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
Not sure if above is required and in Configure I followed the documentation.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, TelemetryConfiguration configuration, IOptionsSnapshot<Settings> settings)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAzureAppConfiguration();
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "eReserve API V1");
c.RoutePrefix = String.Empty;
});
configuration.InstrumentationKey = settings.Value.AppInsightsInstrumentationKey;
app.UseHttpsRedirection();
app.UseCors(builder =>
{
builder.WithOrigins(settings.Value.SignalROrigniURL)
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});
app.UseRouting();
app.UseAuthentication(); // this one first
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<NotifyClientService>("/lockNotification");
});
//app.UseSignalR(routes =>
//{
// routes.MapHub<NotifyClientService>("/lockNotification");
//});
}
Update 2
CORS is also configured where the apis are deployed.
Hello you need to configure cors exactly like I answered on this similar question :
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true));
});
Also I would recommend remove the CORS configuration that you have on Azure to test this code for CORS on the server. After configuring correctly the CORS on the backend you would not need the Azure CORS configuration that you have on Update 2 .
Update
Example on configuring CORS on startup:
public void Configure(IApplicationBuilder app, HostConfiguration hostConfiguration, ILogger<Startup> logger)
{
app.UseCors("CorsPolicy");
}
private static void AddCors(IServiceCollection services, HostConfiguration hostConfiguration)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder.WithOrigins(hostConfiguration.CorsPolicy.Origins.ToArray())
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => hostConfiguration.CorsPolicy.SetIsOriginAllowed));
});
}
I call the private
AddCors
method on theAddAdditionalServices
method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.