The authorization is not working in ASP.net core web API - asp.net-core

I'm trying to implement authorization in asp.ne core webapi web application using jwt tokens.
but when I send a request with bearer authorization and the jwt token generated, the response is always 401 unauthorized
I'm using .Net 5.0 version
what I'm doing wrong ?
here is my startup.cs file
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.Configure<JwtSettings>(Configuration.GetSection("Jwt"));
var jwtSettings = Configuration.GetSection("Jwt").Get<JwtSettings>();
services.AddControllers();
var dataAssemblyName = typeof(CRMContext).Assembly.GetName().Name;
services.AddDbContext<CRMContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default"), x => x.MigrationsAssembly(dataAssemblyName)));
services.AddIdentity<User, Role>(options =>
{
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(1d);
options.Lockout.MaxFailedAccessAttempts = 5;
})
.AddEntityFrameworkStores<CRMContext>()
.AddDefaultTokenProviders();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["JwtAuthentication:JwtIssuer"],
ValidAudience = Configuration["JwtAuthentication:JwtIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtAuthentication:JwtKey"])),
};
});
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddTransient<IAccountService, AccountService>();
services.AddTransient<IApplicationUserService, ApplicationUserService>();
services.AddMvc().AddControllersAsServices();
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Cloud 9", Version = "v1" });
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT containing userid claim",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
});
var security =
new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Id = "Bearer",
Type = ReferenceType.SecurityScheme
},
UnresolvedReference = true
},
new List<string>()
}
};
options.AddSecurityRequirement(security);
});
services.AddAutoMapper(typeof(Startup));
services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
var mappingConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new MappingProfile());
});
IMapper mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);
services.AddAuth(jwtSettings);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
MyServiceProvider.ServiceProvider = app.ApplicationServices;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
// app.UseSwagger();
// app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Ids.Crm.Api v1"));
app.UseAuthorization();
app.UseAuth();
app.UseCors("MyPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseSwagger()
.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "test v1");
c.ConfigObject.AdditionalItems.Add("syntaxHighlight", false);
c.ConfigObject.AdditionalItems.Add("theme", "agate");
});
}

Your request pipeline is missing the authentication middleware. So you couldn't possibly authenticate or possibly authorize. Simply add the middleware before the authorization middleware in the Configure method
app.UseAuthentication();
app.UseAuthorization();
Update: It seems app.UseAuth(); is your authentication middleware. If it is, then place it above the Authorization middleware.
app.UseAuth();
app.UseAuthorization();

I found the solution.... I was declaring a key in the generation of the token which is different from the one I've declared in the appsetting.json
so when the TokenValidationParameters takes the wrong key it was preventing authorization

Related

.Net Core 3.1 - Angular10 Authentication and Antiforgery

I implemented a simple app in .Net Core 3.1. I am using JWT token as Authentication and added Antiforgery like this in ConfigureServices()
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("JWT_SEED"))),
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
context.Token = context.Request.Cookies["JWT"];
return Task.CompletedTask;
}
};
});
services.AddAuthorization(options =>
options.AddPolicy("ValidAccessToken", policy =>
{
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
})
);
services.AddAntiforgery(options => {
options.HeaderName = "X-XSRF-TOKEN";
options.SuppressXFrameOptionsHeader = false;
});
Then, in Configure() I have:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery)
{
app.UseMiddleware<ExceptionMiddleware>();
app.UseCors(options => options
.WithOrigins("https://abc.random.com")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.Use(next => context => {
string path = context.Request.Path.Value;
if (path != null && path.ToLower().Contains("/api")) {
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() {
HttpOnly = false,
Secure = true
});
}
return next(context);
});
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
I also have a method to refresh the antiforgery token
[HttpGet("refreshAntiforgery")]
public IActionResult RefreshAntiforgery() {
var antiforgeryTokens = _antiforgery.GetAndStoreTokens(HttpContext);
HttpContext.Response.Cookies.Append(
"XSRF-TOKEN",
antiforgeryTokens.RequestToken,
new CookieOptions
{
HttpOnly = false,
Secure = true
}
);
return NoContent();
}
In my Angular app I registered in app.module.ts
HttpClientXsrfModule.withOptions({
cookieName: 'XSRF-TOKEN',
headerName: 'X-XSRF-TOKEN'
}),
and in the services I want to use the antiforgery token (I also have the interceptor to add credentials for all requests and also have URLs starting with // to avoid relative URLs)
updatePassword(client: Client): Observable<any> {
let xsrfToken = this.xsrfTokenExtractor.getToken() as string;
let headers = new HttpHeaders()
.set('X-XSRF-TOKEN', xsrfToken);
return this.http.put<Client>(
environment.baseUrls.client +
environment.relativeUrls.updatePassword,
user,
{
headers: headers,
withCredentials: true
}
);
}
The problem is that XSRF-TOKEN coming from .net core app is being set as HttpOnly despite I set the cookie as HttpOnly = false
cookie from browser
Any idea why HttpOnly is being set in XSRF-TOKEN? (I have tried different solutions like cookie policies or check Configure() order, clear cookies from browser, but nothing changes the value)

Authorization happens before authentication after migrating to .net core 3.1

After migrating from .net core 2.2 to .net core 3.1, and after taking some time to fix all the bugs depending on documentations, after running the app, the authorization method get's hit before it requires the user to be authenticated.
I am using OpenId Connect with AD FS for authentication and a custom method called "PermissionGranted" for authorization. And this method get's hit before it requires for the user to be authenticated.
This is the code of my Startup.cs file:
public class Startup
{
private readonly ConfigSettings settings;
private readonly GetSettings configSettings;
private readonly MyMemoryCache myMemoryCache;
public Startup(IWebHostEnvironment env, IConfiguration configuration)
{
configSettings = new GetSettings();
settings = configSettings.getSettings();
Configuration = configuration;
Environment = env;
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
myMemoryCache = new MyMemoryCache();
Log.Logger = new LoggerConfiguration().Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File(settings.LogFile, rollingInterval: RollingInterval.Day)
.WriteTo.ApplicationInsights(new TelemetryConfiguration(settings.AppInsightsConnection), TelemetryConverter.Events)
.CreateLogger();
}
public IConfiguration Configuration { get; }
private IWebHostEnvironment Environment { get; }
public IServiceProvider ServiceProvider { get; set; }
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(Log.Logger);
services.AddSingleton(settings);
services.AddHttpContextAccessor();
services.AddRouting(options => options.LowercaseUrls = true);
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
options.AccessDeniedPath = "/users/denied";
})
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.MetadataAddress = settings.MetadataAddress;
options.ClientId = settings.ClientId;
options.GetClaimsFromUserInfoEndpoint = true;
options.ResponseType = OpenIdConnectResponseType.IdToken;
options.SignedOutRedirectUri = settings.PostLogoutUri;
options.SaveTokens = true;
options.UseTokenLifetime = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = true,
ValidAudience = settings.ClientId,
ValidateIssuer = true,
ValidIssuer = settings.Issuer,
ValidateLifetime = true,
RequireExpirationTime = true
};
options.Events = new OpenIdConnectEvents
{
OnRemoteFailure = context =>
{
context.HandleResponse();
context.Response.Redirect("/Login");
return Task.FromResult(0);
},
OnTicketReceived = context =>
{
// Configuration to make the Authentication cookie persistent for 8 hours (after 8 hours it expires and the user has to re-authenticate)
context.Properties.IsPersistent = true;
context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddHours(8);
return Task.FromResult(0);
}
};
options.Events.OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.Prompt = "login";
return Task.CompletedTask;
};
});
Audit.Core.Configuration.Setup()
.UseSqlServer(config => config
.ConnectionString(settings.ConnectionString)
.TableName("AuditEvents")
.IdColumnName("EventId")
.JsonColumnName("AuditData")
.LastUpdatedColumnName("LastUpdatedDate"));
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
services.AddApplicationInsightsTelemetry(settings.AppInsightsConnection);
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
// Use NewtonsoftJson and custom date format
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
});
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(15);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true; // Make the session cookie essential
});
services.AddAuthorization(options =>
{
options.AddPolicy("Permissions", policy => policy.RequireAssertion(context => PermissionGranted(context)));
});
services.AddDbContext<PasswordManagerContext>(options =>
options.UseSqlServer(settings.ConnectionString));
services.AddSingleton<MyMemoryCache>();
services.AddPaging(options =>
{
options.ViewName = "PagerUI";
options.HtmlIndicatorDown = " <span>↓</span>";
options.HtmlIndicatorUp = " <span>↑</span>";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Login}/{action=Index}/{id?}");
//endpoints.MapFallbackToController("Index", "Home");
});
ServiceProvider = app.ApplicationServices;
}
According to official docs, the order of these:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints
matters but in my code they are ordered correctly.
What could be missing or what could possibly be wrong in the configuration?
Thanks in advance

With JWT token and policy set, I get unauthorized 401

I follow the tutorial link below.
https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login
I am trying to understand how it works and I want to use role-based authentication using this token. so I made another policy in the Startup.cs file as below.
And I tried to use it like [Authorize(Policy = "admin")] the controller but every time I try I get unauthenticated using postman.
What am I missing? how to make roles-based authentication based on the tutorial?
Configure
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.WithOrigins("http://localhost:4200", "http://localhost:44318")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
});
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
});
// api user claim policy
services.AddAuthorization(options =>
{
options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
});
services.AddAuthorization(options =>
options.AddPolicy("admin", policy => policy.RequireRole("admin"))
);
var builder = services.AddIdentityCore<AppUser>(o =>
{
// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
});
builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);
builder.AddEntityFrameworkStores<CDSPORTALContext>().AddDefaultTokenProviders().AddRoles<IdentityRole>();
//.AddRoles<IdentityRole>()
services.AddControllers();
services.AddAutoMapper(typeof(Startup));
services.AddSingleton<IJwtFactory, JwtFactory>();
services.TryAddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IRegionRepository, RegionRepository>();
services.AddScoped<IRegionService, RegionService>();
services.AddScoped<IEmailHelper, EmailHelper>();
}
// 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.UseCors("CorsPolicy");
app.UseExceptionHandler(
builder =>
{
builder.Run(
async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
}
});
});
app.UseRouting();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Client";
spa.UseAngularCliServer(npmScript: "start");
});
}
}
Auth Controller
// POST api/auth/login
[HttpPost("login")]
public async Task<IActionResult> Post([FromBody]CredentialsViewModel credentials)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var identity = await GetClaimsIdentity(credentials.UserName, credentials.Password);
if (identity == null)
{
//return null;
return BadRequest(Error.AddErrorToModelState("login_failure", "Invalid username or password.", ModelState));
}
var id = identity.Claims.Single(c => c.Type == "id").Value;
var user = await _userManager.FindByIdAsync(id);
IList<string> role = await _userManager.GetRolesAsync(user);
var jwt = await Tokens.GenerateJwt(identity, role[0], _jwtFactory, credentials.UserName, _jwtOptions, new JsonSerializerSettings { Formatting = Formatting.Indented });
return new OkObjectResult(jwt);
}
I tried with all method and none of them working
[Authorize(Policy = "ApiUser")]
[HttpGet("getPolicy")]
public string GetPolicy()
{
return "policyWorking";
}
[Authorize(Roles = "admin")]
[HttpGet("getAdmin")]
public string GetAdmin()
{
return "adminWorking";
}
[Authorize ]
[HttpGet("getAuthorize")]
public string GetAuthorize()
{
return "normal authorize Working";
}
Decoded Token
"jti": "840d507d-b2d0-454b-bd1f-007890d3e669",
"iat": 1587699300,
"rol": "api_access",
"id": "1ac370e2-f5e9-4404-b017-8a3c087e2196",
"nbf": 1587699299,
"exp": 1587706499
I forgot to add this to appsetting.
"JwtIssuerOptions": {
"Issuer": "webApi",
"Audience": "http://localhost:4200/"
}

Server cannot authorize it's own tokens

Here is the setup, I have an auth server that issues tokens to an angular website. I have a controller inside the AuthServer that needs to use the [Authorize] system to only allow JWT tokens that are valid. When I check the User variable in my controller it is always null but when I check the HttpRequestHeaders on the controller I see the token being sent.
I also have an Api server that I implemented using the JWT tokens and [Authorize] system very easily.
Another layer, I am running both Api and Auth servers in docker containers.
My entire Startup.cs file from AuthServer:
var connectionString = Configuration.GetConnectionString("Default");
if (_env.IsDevelopment())
{
try
{
using (AppIdentityDbContext identityDb =
new AppIdentityDbContextFactory(connectionString).Create())
{
int Pendings = identityDb.Database.GetPendingMigrations().Count();
identityDb.Database.Migrate();
}
using (PersistedGrantDbContext persistGrantDb =
new PersistedGrantDbContextFactory(connectionString).Create())
{
int Pendings = persistGrantDb.Database.GetPendingMigrations().Count();
persistGrantDb.Database.Migrate();
}
}
catch (Exception)
{
}
}
services.AddControllersWithViews();
services.AddDbContextPool<AppIdentityDbContext>(options => options.UseSqlServer(connectionString));
services
.AddIdentity<AppUser, IdentityRole>(config=> {
config.User.RequireUniqueEmail = true;
config.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();
services.AddIdentityServer().AddDeveloperSigningCredential()
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration.GetConnectionString("Default"));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = (int)TimeSpan.FromDays(1).TotalSeconds; // interval in seconds
})
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddAspNetIdentity<AppUser>()
.AddProfileService<AppUserProfileService>()
.AddJwtBearerClientAuthentication();
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme,
jwtOptions =>
{
// jwt bearer options
jwtOptions.Authority = _env.IsDevelopment() ? "https://localhost:5001" : "";
jwtOptions.RequireHttpsMetadata = _env.IsDevelopment() ? false : true;
jwtOptions.Audience = "resourceapi";
jwtOptions.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateAudience = false,
ValidateIssuer = _env.IsDevelopment() ? false : true,
ValidateActor = false,
ValidateIssuerSigningKey = false
};
},
referenceOptions =>
{
// oauth2 introspection options
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()));
services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
services.AddSingleton<IEmailSender, SmtpSender>();
Configure Section:
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();
var forwardOptions = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
RequireHeaderSymmetry = false
};
forwardOptions.KnownNetworks.Clear();
forwardOptions.KnownProxies.Clear();
// ref: https://github.com/aspnet/Docs/issues/2384
app.UseForwardedHeaders(forwardOptions);
}
app.UseCors("AllowAll");
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Check for user inside of AccountController: Controller
var u = User;
var _user = await _userManager.GetUserAsync(u);
var e = this._httpContextAccessor;

Bearer Authentication with ASP.NET Core RC2 404 instead of 403

I am trying to use Bearer Authentication with ASP.NET Core RC2. It is working with user authenticad and has the role, but when the user is not authorized (authenticad but dont have the role) I get a 404 error instead of 403 expected.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder =>
{
builder
.WithOrigins("*")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
}
);
});
services.AddIdentity<AppUser, AppRole>().AddEntityFrameworkStores<AppIdentityDbContext, int>();
services.AddAuthorization();
services.AddMvc(config => {
var policy = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
}).AddJsonOptions(options =>
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver()
);
}
// 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.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/home/error");
}
app.UseStaticFiles();
var signingKey = GetSigningKey();
app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme,
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = new TokenValidationParameters()
{
IssuerSigningKey = signingKey,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidAudience = "MyAudience",
ValidIssuer = "MyIssuer"
}
});
app.UseCors(config =>
{
config.AllowCredentials();
config.AllowAnyOrigin();
config.AllowAnyHeader();
config.AllowAnyMethod();
});
app.UseIdentity();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
public static SecurityKey GetSigningKey()
{
var plainTextSecurityKey = "This is my shared, not so secret, secret!";
return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
}
Using app.UseIdentity() will add CookieAuthentication to your application and hence all unauthenticated requests will redirect to /Account/Login.
Probably you haven't added any routes to handle this so it gave you a 404.
Source: https://github.com/aspnet/Identity/blob/dev/src/Microsoft.AspNetCore.Identity/BuilderExtensions.cs
Please check position app.UseIdentity() also MVC routing app.UseMvc().authenicate code should be below of app.useIdenetity() and above of Mvc rotuing. like this: app.UseApplicationInsightsExceptionTelemetry();
app.UseStaticFiles();
app.UseIdentity();
app.UseCors(builder =>
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
);
app.UseSwagger();
app.UseSwaggerUi();
ConfigureAuth(app);
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "index");
});