.Net Core 2.0 Web API OpenIddict Authorization: redirecting to index instead of returning json data - openiddict

So, the problem is that when I use the AuthorizeAttribute on top of my api controller, it stops working the expected way.
When I call a getAllUsers action, instead of returning the users in json format, the Identity somehow redirects to index.html and then I get a json parser error in my Angular client app, because html is not valid json data that can be parsed.
This started to happen after upgrading to Asp.Net Core 2.0.
I think that perhaps I have to change something in my Startup.cs or Program.cs. But I can't figure out what.
I have followed the Refresh Token Sample on OpenIddict for the new Core 2.0, and everything seems to be ok.
So here is my code...
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options => {
options.UseSqlServer(Configuration.GetConnectionString("LocalDB"))
.UseOpenIddict();
});
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IRoleRepository, RoleRepository>();
services.AddScoped<IManadRepository, ManadRepository>();
services.AddScoped<IManadRubricaRepository, ManadRubricaRepository>();
services.AddScoped<IManadSistemaRepository, ManadSistemaRepository>();
services.AddScoped<IRestituicaoRepository, RestituicaoRepository>();
services.AddTransient<ApplicationDbSeedData>();
services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
options.User.RequireUniqueEmail = true;
options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddOpenIddict(options =>
{
options.AddEntityFrameworkCoreStores<ApplicationDbContext>();
options.AddMvcBinders();
options.EnableTokenEndpoint("/connect/token");
options.AllowPasswordFlow();
options.AllowRefreshTokenFlow();
if (!_env.IsProduction())
options.DisableHttpsRequirement();
});
// Add framework services.
services.AddMvc();
services.AddAuthentication()
.AddOAuthValidation();
services.AddAuthorization();
services.AddTransient<IMailSender, MailjetSender>();
services.AddScoped<IManadParser, ManadParser>();
}
public void Configure(IApplicationBuilder app, ApplicationDbSeedData dbDataSeeder)
{
if (_env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
else
{
app.UseExceptionHandler("/Home/Error");
}
Mapper.Initialize(cfg =>
{
cfg.AddProfile<AutoMapperProfile>();
});
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
dbDataSeeder.EnsureSeedData().Wait();
}
UsersController.cs
[Route("api/[controller]")]
[Authorize]
public class UsersController : Controller
{
[HttpGet]
[Authorize(Roles = "Administrador")]
public IActionResult GetAllUsers()
{
try
{
var result = _repository.GetAllUsers();
return Ok(result);
}
catch (Exception ex)
{
_logger.LogError($"Failed to get all users: {ex}");
return BadRequest(ex.Message);
}
}
}
If I put a breakpoint in the GetAllUsers method, it never gets hitted. Somehow because of authorization, the application redirects to index.html before.
Program.cs
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
By the way, authentication is working. I am able to get the tokens, but unable to authorize the controller access.

Solved it. Just needed some bit of configuration just like I thought. Just add DefaultAuthenticateScheme option like this:
services.AddAuthentication(options => options.DefaultAuthenticateScheme = OAuthValidationDefaults.AuthenticationScheme)
.AddOAuthValidation();
After adding this, the controller started to work correctly, resulting json data and not index.html.

Related

ASP .NET Core CORS issue with Google authentication on redirect

Been following this tutorial in order to implement Google authentication in my web API but on the client side (using React and axios to do the request) the authentication process gets interrupted with this CORS issue and I'm struggling to sort it out:
Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?(etc)' (redirected from 'https://localhost:44320/Photo/b997d788-3812-41d0-a09d-1a597eee9bad') from origin 'https://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This is the Startup.cs file:
namespace rvc
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
});
});
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options =>
{
options.LoginPath = "/account/google-login";
}).AddGoogle(options =>
{
options.ClientId = "clientId";
options.ClientSecret = "secret";
});
services.AddScoped<PhotoService>();
services.AddScoped<TagService>();
services.AddScoped(_ => new BlobServiceClient(Configuration.GetConnectionString("AzureBlobStorage")));
services.AddDbContext<Data.DataContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "rvc", Version = "v1" }); });
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "rvc v1"));
}
app.UseHttpsRedirection();
if (env.IsProduction())
{
app.UseSpa(spa => { });
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "client")),
EnableDefaultFiles = true
});
}
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
}
}
The Route("google-login") gets called but the Url.Action("GoogleResponse") is not reached. These are the Google Authentication methods:
namespace rvc.Controllers;
[AllowAnonymous, Route("account")]
public class AccountController : Controller
{
[Route("google-login")]
public IActionResult GoogleLogin()
{
var properties = new AuthenticationProperties {RedirectUri = Url.Action("GoogleResponse")};
return Challenge(properties, GoogleDefaults.AuthenticationScheme);
}
[Route("google-response")]
public async Task<IActionResult> GoogleResponse()
{
var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
var claims = result.Principal?.Identities.FirstOrDefault()
?.Claims.Select(claim => new
{
claim.Issuer,
claim.OriginalIssuer,
claim.Type,
claim.Value
});
return Json(claims);
}
}
This is probably because from the server you use redirect, which triggers CORS (even if from your server you allow it).
you have to return the redirect URL to your front-end in some other way, capture it from the front-end app and then call the URL you need to invoke.

Visual studio's ASP.NET core with angular template always returns 401

I'm using Microsoft Visual Studio Community 2019 Version 16.10.2. I created an ASP.net core 5 project from their template "ASP.net core with Angular" with Authentication checked. But Every time I request an API Method marked with the attribute [Authorize] I get 401.
Their template was supposed to work with no problem but I got some trouble logging in. I fixed them but, the only problem I can't figure out how to fix is the 401 code returned ASP.
I read the doc several times but I could not find any useful information.
The thing is: I can create accounts and login with no problem. When I login, the server returns the token. From the Angular app it shows the name of the logged-in user. But when to access an [Authorize] controller it returns 404.
Here is the link of the project I pushed to github for better debugging.
Here is the startup code:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(op =>
{
// I added these lines because I was getting the error "Error: Client Angular_identity_test is not allowed access to scope Angular."
op.Clients[0].AllowedScopes = new List<string> { "Angular", "identity", "testAPI" };
op.ApiScopes = new Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ApiScopeCollection(new List<ApiScope> { new ApiScope("Angular"), new ApiScope("identity"), new ApiScope("testAPI") });
op.ApiResources.AddApiResource("Angular", conf => conf.WithScopes(new string[] { "Angular", "identity", "testAPI" }));
op.ApiResources.AddApiResource("identity", conf => conf.WithScopes(new string[] { "Angular", "identity", "testAPI" }));
op.ApiResources.AddApiResource("testAPI", conf => conf.WithScopes(new string[] { "Angular", "identity", "testAPI" }));
});
services.AddAuthentication()
.AddIdentityServerJwt();
services.AddControllersWithViews();
services.AddRazorPages();
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
// In public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseHttpsRedirection();
app.UseStaticFiles();
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
app.UseRouting();
// I added this line because some people say that fixed their problems.
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
In the appsettings.json there is:
"IdentityServer": {
"Clients": {
"Angular_identity_test": {
"Profile": "IdentityServerSPA"
}
}
}
And the controller that keeps return 401:
[Authorize()]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
So you say, But when to access a [Authorize] controller it returns 404. use this below code, instead of [Authorize].
[Authorize(AuthenticationSchemes = "Bearer")]
It will resolve your issue.
UPDATE
Use this below code and i assume that your Token is place of appsettings.development.json file. like "TokenKey":"super secret key",
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters=new TokenValidationParameters
{
ValidateIssuerSigningKey=true,
IssuerSigningKey=new SymmetricSecurityKey( Encoding.UTF8.GetBytes(config["TokenKey"]) ),
ValidateIssuer=false,
ValidateAudience=false
};
});
Hope it will resolve your issue.
This will be a proxy issue. In your CLIENTAPP go to the proxy.conf.js and add your controllers route into the PROXY_CONFIG->context array (like "/weatherforecast" is). Then restart your application. You don't need to change .NET Core middleware or services.
UPDATE
I added this DI BASE_URL into my service constructor and it works fine now.
constructor(private http: HttpClient, #Inject('BASE_URL') private bUrl: string) {
this.baseUrl = bUrl + "api/v1/items"; // my endpoint
}

ASP.NET Core 5: OpenIDConnect breaking default/root route

I have an ASP.NET Core 5 MVC app, with the default/root route set like this inside PageController:
[AllowAnonymous]
[Route("/")]
public IActionResult __Home(int? parent)
{
return View();
}
This worked fine until I added OpenIdConnect authentication. After that, the root (/) page no longer routes to __Home in the PageController, it just returns a blank page. All other pages route just fine.
When I comment out this:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAdB2C");
then / works again, so I know it's something to do with the authentication. As you can see, I have added [AllowAnonymous] to that action.
I have this in my startup:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
});
Any ideas on how to fix this? I know it's unconventional to have the default/root route in a weird controller/action like that, but there are reasons for it, so I'm hoping it can still work.
More Info:
I found that if I move app.UseEndpoints above app.UseAuthentication, then the home page shows. After logging in (with B2C), however, it goes into an infinite loop (i.e. the authentication token doesn't stick?).
EDIT: My Startup.cs class
using Blank.Models;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
namespace Blank
{
public class Startup
{
private readonly AppSettings appSettings = null;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
this.appSettings = new AppSettings();
this.Configuration.Bind(this.appSettings);
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAdB2C");
services.AddSession();
services.Configure<OpenIdConnectOptions>(Configuration.GetSection("AzureAdB2C"));
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.Configure<AppSettings>(this.Configuration);
services.AddEntityFrameworkSqlServer().AddDbContext<BlankDBContext>(
Options => Options.UseSqlServer(Microsoft.Extensions.Configuration.ConfigurationExtensions.GetConnectionString(this.Configuration, "BlankDatabase"))
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Page}/{action=Index}/{id?}");
});
}
}
}
Edit 2
I think that app.UseAuthentication() is breaking/returning the blank page, because when I put the following code before app.UseAuthentication() I get something on the home page, and if it's after then blank:
app.Use(async (context, next) =>
{
var endpoint = context.GetEndpoint();
if (endpoint != null)
{
await context.Response.WriteAsync("<html> Endpoint :" + endpoint.DisplayName + " <br>");
if (endpoint is RouteEndpoint routeEndpoint)
{
await context.Response.WriteAsync("RoutePattern :" + routeEndpoint.RoutePattern.RawText + " <br>");
}
}
else
{
await context.Response.WriteAsync("End point is null");
}
await context.Response.WriteAsync("</html>");
await next();
});
So perhaps it has to do with my authentication? Here's my appsettings.json:
"AzureAdB2C": {
"Instance": "https://abc.b2clogin.com",
"Domain": "abc.onmicrosoft.com",
"ClientId": "62...f1",
"TenantId": "7e...ae",
"SignUpSignInPolicyId": "B2C_1_SUSI",
"SignedOutCallbackPath": "/"
},
Turns out the problem was this in my appsettings.json:
"SignedOutCallbackPath": "/"
Removing this fixed the problem, and the home page now loads correctly.

.netcore web API Post does not work without SSL

I have an MVC core 2.2 application with Controllers, API controllers, and some Views. Some of the Views make use of the API endpoints within the same application. All was ok until I enabled TLS 1.2 in my windows server.
Now all endpoints decorated as GET methods work. But all POSTs have stopped working with chrome reporting this POST 'link' net::ERR_CONNECTION_RESET.
Other browsers catch exception at fail and display my error text with object
$.ajax({
url: "/api/Cart",
method: "post",
data: JSON.stringify(vm),
contentType: "application/json"
}).done(function(result) {
console.log(result);
}).fail(function(ex) {
console.log("Error occured while adding to cart" + ex)
});
I want to be able to POST even without SSL. I have disabled TLS 1.2 and restarted but still the same result.
If I browse the site with https://, POST and GET endpoints all work perfectly but if I browse with HTTP://, only GET endpoints work, all POST endpoints do not work.
I have combed the internet for almost 5 hours for something I thought would be simple.
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("DataConnection");
services.AddDbContext<DataContext>(options => options.UseSqlServer(connectionString));
//Inject Connection String to other Classes
services.AddSingleton(_ => connectionString);
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(1);
});
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddMediatR(typeof(CreateProductCommand).Assembly, typeof(CreateProductCommandHandler).Assembly);
services.AddAutoMapper(typeof(MappingProfile));
// Add memory cache services
services.AddMemoryCache();
services.AddMvc(o =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
o.Filters.Add(new AuthorizeFilter(policy));
}) .SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_2);
}
// HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
var serviceProvider = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope().ServiceProvider;
DataContextSeed.Initialize(serviceProvider);
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Above is the Startup class and a sample post is here
[HttpPost]
public IActionResult Post([FromBody] SaleItemDTO md)
{
if(md != null)
{
if(md.Quantity <= md.Stock)
{
_sales.SalesPerson = User.Identity.Name;
_sales.SalesType = md.SalesType;
return Ok(_sales.ItemsInDb);
}
}
return BadRequest(new { Message = "Not Valid Content posted" });
}
Help with your thoughts.

Asp.net Core MVC Authorize Attribute not blocking

Authorize attribute is not working. I am not logged in and it allows me to access this function.
i have played around with my Startup.cs attached at the bottom. Please help me get started with this. I have successfully used these methods on previous version of MVC, but I am not successful yet with MVC core.
After this I am looking to add roles. Any direction on where to start with that would be appreciated.
Thanks
public class SecurityAccessController : Controller
{
private SecurityAccessDbContext SecurityAccessDbContext { get; set; }
public SecurityAccessController([FromServices] SecurityAccessDbContext SecurityAccessDbContext)
{
this.SecurityAccessDbContext = SecurityAccessDbContext;
}
// GET: /<controller>/
[Authorize]
public IActionResult Index()
{
return View();
}
}
This is my Start Up.cs
Updated as recommended by the below comment
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMemoryCache();
services.AddSession();
//Added
services.AddBootstrapPagerGenerator(options => {options.ConfigureDefault();});
//Database services
services.AddEntityFrameworkSqlServer().AddDbContext<SecurityAccessDbContext>(options => { options.UseSqlServer(Configuration["ConnectionStrings:Accumatica"]); });
services.AddEntityFrameworkSqlServer().AddDbContext<AcumaticaDbContext>(options => { options.UseSqlServer(Configuration["ConnectionStrings:Accumatica"]); });
services.AddEntityFrameworkSqlServer().AddDbContext<RMADbContext>(options => { options.UseSqlServer(Configuration["ConnectionStrings:Accumatica"]); });
services.AddEntityFrameworkSqlServer().AddDbContext<WarrantyDbContext>(options => { options.UseSqlServer(Configuration["ConnectionStrings:Accumatica"]); });
services.AddEntityFrameworkSqlServer().AddDbContext<GenericDbContext>(options => { options.UseSqlServer(Configuration["ConnectionStrings:Accumatica"]); });
services.AddEntityFrameworkSqlServer().AddDbContext<ApplicationIdentityDbContext>(options => { options.UseSqlServer(Configuration["ConnectionStrings:Accumatica"]); });
services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
options.Cookies.ApplicationCookie.LoginPath = "/Account/Login";
options.Cookies.ApplicationCookie.AccessDeniedPath = "/Home/AccessDenied";
})
.AddEntityFrameworkStores<ApplicationIdentityDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
services.AddTransient<IEmailSender, AuthMessageSender>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseSession();
app.UseIdentity();
app.UseMvcWithDefaultRoute();
}
Add Identity before adding Mvc. Furthermore you don't need to add Authorization as that's already done when adding Identity as seen here. You also can configure your identity options such as the login path, without needing configure CookieAuthenticationOptions. Instead you can configure it when adding Identity.
Here's a snippet of what the code could look like.
// Remove me
// services.AddAuthorization();
// Remove me too
// services.Configure<CookieAuthenticationOptions>(options =>
// ....
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Cookies.ApplicationCookie.LoginPath = "/Account/Login";
options.Cookies.ApplicationCookie.AccessDeniedPath = "/Home/AccessDenied";
options.Cookies.ApplicationCookie.AutomaticChallenge = true;
options.Cookies.ApplicationCookie.AutomaticAuthenticate = true;
})
.AddEntityFrameworkStores<ApplicationIdentityDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
I found the issue
the file launchsettings.json had
"iisSettings": {
"windowsAuthentication": true,
I changed to
"iisSettings": {
"windowsAuthentication": false,
The above answer also helped me, but I can add that if you want the [AllowAnonymous] attribute to work you will also need to change the anonymousAuthentication to true:
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,