Reputation: 31
My front-end is running on localhost:4200 and back-end on localhost:5000 I have setup Windows Authentication on the back-end and front-end as below
Program.cs
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.Build();
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<IISOptions>(options =>
{
options.AutomaticAuthentication = true;
});
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddAuthorization(options => {
options.AddPolicy("AllUsers", policy => {
policy.AddAuthenticationSchemes(IISDefaults.AuthenticationScheme);
policy.RequireRole("S - 1 - 1 - 0");
});
});
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
var mvcBuilder = services.AddMvc();
mvcBuilder.AddJsonOptions(opts => opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());
services.AddAutoMapper(typeof(Startup));
services.AddSingleton<IConfigurationRoot>(_config);
services.AddRouting();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
DefaultFilesOptions options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("index.html");
app.UseDefaultFiles(options);
app.UseAuthentication();
app.UseCors("CorsPolicy");
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
// Route all unknown requests to app root
app.Use(async (context, next) =>
{
await next();
// If there's no available file and the request doesn't contain an extension, we're probably trying to access a page.
// Rewrite request to use app root
if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = "/index.html"; // Put your Angular root page here
context.Response.StatusCode = 200; // Make sure we update the status code, otherwise it returns 404
await next();
}
});
}
On the controller,
[Authorize]
[Route("/api/service/testWinAuth")]
[EnableCors("CorsPolicy")]
public class TestWinAuth : Controller
{
....
}
In the method within this controller I have,
[Route("/{id}/{withVoids?}")]
[HttpGet]
[Authorize]
public Object testMethod(Int64? id, String withVoids)
{
var userId = HttpContext.User.Identity.Name;
}
launchSettings.json
{
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:5000/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"webapi": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5001/"
}
}
}
On the front-end side, I have the following settings:
proxy.conf.json
{
"/api": {
"target": "http://localhost:5000",
"secure": false
}
}
The http request is set up to use the option withCredentials = true
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
if (!options) {
const headers = new Headers({ 'Content-Type': 'application/json' });
options = new RequestOptions({ headers: headers, withCredentials: true });
}
// noinspection TypeScriptUnresolvedFunction
return super.get(url, options)
.map(r => r)
.catch((error: any): Observable<Response> =>
this.errorDisplayAndRedirect(error));
}
When accessing the URL localhost:4200, it asks for username and password and displays the page after authenticating. When I click on a button which sends a Get request, it asks for authentication again and this time it does not authenticate and I get 401 Unauthorized error. But, When I access the back-end directly using the URL, it asks for username and password and authenticates as expected. How do I correctly pass authentication information from front-end to back-end?
Upvotes: 3
Views: 6620
Reputation: 41
After having read in the related article: implementing windows authentication in an angular application and a stand-alone-web-api - that "You can’t use SupportsCredentials as true along with * for the origins.", I notice that the following line of code contradicts the above point.
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
I.e. while you are allowing credentials, you are also allowing any origin.
Have you considered replacing the .AllowAnyOrigin(), with say, .WithOrigins("http://localhost:4200"), or something similar?
Keep in mind that I did not use your code, but was having the same issue, but after providing a specific origin, it started working for me.
Good luck.
Upvotes: 2