Dotnet Core 2.0 Authorization failed for user: (null) - asp.net-core

My code was working perfectly with .net core 2.0. I'm not sure what went wrong. Application is throwing error during authorization. Error message and startup class code below.
> Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information:
Policy execution successful.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information:
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information:
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information:
Authorization failed for the request at filter
'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information:
Authorization failed for the request at filter
'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
namespace API
{
public class Startup
{
public IConfigurationRoot Configuration { get; }
public void ConfigureScopeServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options => options.UseMySql(Configuration.GetConnectionString("Default")));
}
public void ConfigureCompressionService(IServiceCollection services)
{
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
services.AddResponseCompression(options => { options.Providers.Add<GzipCompressionProvider>(); });
}
public void ConfigureJWTService(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("ApplicationConfiguration:TokenOptions:SigningKey").Value)),
ValidateIssuer = true,
ValidIssuer = Configuration.GetSection("ApplicationConfiguration:TokenOptions:Issuer").Value,
ValidateAudience = true,
ValidAudience = Configuration.GetSection("ApplicationConfiguration:TokenOptions:Audience").Value,
ValidateLifetime = true,
NameClaimType = JwtRegisteredClaimNames.Sub,
RoleClaimType = "Roles"
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.TokenValidationParameters = tokenValidationParameters;
});
}
public void ConfigureServices(IServiceCollection services)
{
this.ConfigureScopeServices(services);
this.ConfigureCompressionService(services);
this.ConfigureJWTService(services);
services.Configure<ApplicationConfiguration>(Configuration.GetSection("ApplicationConfiguration"));
//Customized Response Object to Map MiddleWare Response Object
var formatterSettings = JsonSerializerSettingsProvider.CreateSerializerSettings();
formatterSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
ResponseFormatter formatter = new ResponseFormatter(formatterSettings, ArrayPool<Char>.Create());
services.AddMvcCore()
.AddApiExplorer()
.AddAuthorization()
.AddFormatterMappings()
.AddDataAnnotations()
.AddJsonFormatters()
.AddCors()
.AddMvcOptions(
options =>
{
options.OutputFormatters.RemoveType<JsonOutputFormatter>();
options.OutputFormatters.Insert(0, formatter);
}
);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCors(
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
app.UseMvc();
app.UseResponseCompression();
}
}
}

I think you missed authentication middleware: app.UseAuthentication().
Please try this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCors(
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
app.UseAuthentication();
app.UseMvc();
app.UseResponseCompression();
}

Related

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

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

Authentication and Authorization in .Net Core 5 and Angular 10 using JWT problem

Hello I'm trying make authorization using JWT token so when not authorized user request api or request service it decline,
I've used JWT token with claim Role and made Job column in my database as role so that It will get the role from it
the problem is I can't decode the token or tbh I tried my best with the help of identity to decode it but I sure can't
that's my startup.cs
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.AddAuthentication();
services.AddCors(options =>
{
options.AddPolicy("EnableCORS", Builder =>
{
Builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddDbContext<media_cloudContext>(option => option.UseSqlServer(Configuration.GetConnectionString("MediaCloudCS")));
services.AddScoped<ILoginService, LoginService>();
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "MediaCloudApi", 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", "MediaCloudApi v1"));
}
app.UseHttpsRedirection();
app.UseCors("EnableCORS");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
I added JWT package and tried to add default scheme but it can't define it and the only thing avilable JWTBearerExtension
that's my token creation service
public class TokenHelper
{
public const string Issuer = "http://MediaCloud.com";
public const string Audience = "http://MediaCloud.com";
public const string Secret = "OFRC1j9aaR2BvADxNWlG2pmuD392UfQBZZLM1fuzDEzDlEpSsn+btrpJKd3FfY855OMA9oK4Mc8y48eYUrVUSw==";
public static string GenerateSecureSecret()
{
var hmac = new HMACSHA256();
return Convert.ToBase64String(hmac.Key);
}
public static string GenerateToken(UserInfo user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Convert.FromBase64String(Secret);
var claimsIdentity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, user.Id.ToString()),
new Claim(ClaimTypes.Role, user.Job),
});
var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = claimsIdentity,
Issuer = Issuer,
Audience = Audience,
Expires = DateTime.Now.AddMinutes(15),
SigningCredentials = signingCredentials,
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
and that's the get request from the controller
[HttpGet,Authorize]
public async Task<ActionResult<IEnumerable<UserInfo>>> GetUserInfos()
{
return await _context.UserInfos.ToListAsync();
}
and the error code from postman
STATUS 500 INTERNAL SERVER ERROR
System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 69
Content-Type: application/json
Host: localhost:44371
User-Agent: PostmanRuntime/7.28.4
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IjciLCJyb2xlIjoiYWRtaW4iLCJuYmYiOjE2MzU5NzMyMDYsImV4cCI6MTYzNTk3NDEwNiwiaWF0IjoxNjM1OTczMjA2LCJpc3MiOiJodHRwOi8vTWVkaWFDbG91ZC5jb20iLCJhdWQiOiJodHRwOi8vTWVkaWFDbG91ZC5jb20ifQ.QjOC2ixirm9zmMmFDRO28JPd1Q97mq_M8bxlmmgT8EU
Postman-Token: 3911736a-ea2b-4273-ba35-d0315a560e71
I think the problem is the default schema but I can't add it and I'm new to .net core
you have to add to ConfigureServices(IServiceCollection services) of your startup file the code similar this one
var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Tokens:Key"]));
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = key,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidateIssuer = false,
ValidAudience =Configuration["Tokens:Audience"] ,
ValidateAudience = true
};
});
and it is better to use appsettings to keep token parameters then to hard code them. Add somethig like this to to appsettings.json
"Tokens": {
"Key": "xxxxxx"
"Audience": "xxxxx",
"Issuer": "xxxx"
}

.NET CORE 3.1 ERROR 500 during WebSocket handshake

I am using SignalR on my .net core 3.1 API and it all works on localhost
hosting my app on ubuntu 20.4 will result in error 500 during handshake...
I am pretty sure I am missing something on my Apache configs...
error is just "Error during WebSocket handshake: Unexpected response code: 500" no extra data although -> options.EnableDetailedErrors = true
any idea why it doesn't work?
this my Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
services.AddSignalR(options =>
{
options.EnableDetailedErrors = true;
}).AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.PropertyNamingPolicy = null;
});
services.AddControllers();
// Configure Compression level
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
// Add Response compression services
services.AddResponseCompression(options =>
{
options.Providers.Add<GzipCompressionProvider>();
options.EnableForHttps = true;
});
services.AddTransient<IActionContextAccessor, ActionContextAccessor>();
JsonSerializerSettings jsonSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Include,
// ContractResolver = new CamelCasePropertyNamesContractResolver()
};
jsonSettings.Converters.Add(new StringEnumConverter());
services.AddMvc().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
services.AddDistributedMemoryCache();
services.AddOptions();
services.Configure<IConfiguration>(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IDistributedCache cache)
{
app.UseResponseCompression();
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<AnalyticsHub>("/AnalyticsHub");
endpoints.MapHub<CampaignHub>("/CampaignHub");
endpoints.MapHub<LinkHub>("/LinkHub");
});
app.UseStaticFiles();
}
the error:

Identity Server 4 - Audience validation failed error

I encounter this error in my API IDX10214: Audience validation failed. Audiences: 'https://localhost:44337/resources'. Did not match: validationParameters.ValidAudience: 'joborderingapi' or validationParameters.ValidAudiences: 'null'
I've been trying to solve this for 2 days already and can't figure out yet about how to solve it.
I have the following applications:
Client App (Angular 7)
Identity Server
API
I was able to login successfully to Identity Server in my Client app and was able to get the token but when I used the token to connect to the API method it throws this error IDX10214: Audience validation failed. Audiences: 'https://localhost:44337/resources'. Did not match: validationParameters.ValidAudience: 'joborderingapi' or validationParameters.ValidAudiences: 'null'.
I followed the answer from Identity Server 4 with EF Identity DB Issue and checked the three tables (ApiResources, ApiScopes, ClientScopes), the values are correct, joborderingapiis enabled in ApiResources, in ApiScopes it is linked to ApiResource and in ClientScopes it is linked to the Client
Here is my API Startup.cs
public void ConfigureServices(IServiceCollection services)
{
var apiIdpAuthority = Configuration["AppSettings:IdpAuthority"];
var apiName = Configuration["AppSettings:ApiName"];
var apiSecret = Configuration["AppSettings:ApiSecret"];
var requireHttps = Convert.ToBoolean(Configuration["AppSettings:RequireHttps"]);
var httpsPort = Configuration["AppSettings:HttpsPort"];
var applicationUrl = Configuration["AppSettings:ApplicationUrl"];
services.Configure<ClientAppSettings>(Configuration.GetSection("ClientAppSettings"));
services.AddDbContext<JobOrderingDataContext>(options => options.UseSqlServer(Configuration.GetConnectionString("JobOrderingDB")));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
IdentityModelEventSource.ShowPII = true;
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = apiIdpAuthority;
options.RequireHttpsMetadata = requireHttps;
options.ApiName = apiName;
options.ApiSecret = apiSecret;
});
services.AddCors(options =>
{
// this defines a CORS policy called "default"
options.AddPolicy("default", policy =>
{
policy.WithOrigins(apiIdpAuthority, applicationUrl)
.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin()
.AllowCredentials();
});
});
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
services.AddHsts(options =>
{
options.Preload = true;
options.IncludeSubDomains = true;
options.MaxAge = TimeSpan.FromDays(60);
});
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
options.HttpsPort = Convert.ToInt32(httpsPort);
});
}
// 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();
}
else
{
app.UseHsts();
}
app.UseCors("default");
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseHttpsRedirection();
app.UseCookiePolicy();
var locale = Configuration["SiteLocale"];
var supportedCultures = new List<CultureInfo> { new CultureInfo("en-US") };
if (supportedCultures.Where(x => x.Name == locale).Count() == 0)
{
supportedCultures.Add(new CultureInfo(locale));
}
RequestLocalizationOptions localizationOptions = new RequestLocalizationOptions()
{
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures,
DefaultRequestCulture = new RequestCulture(locale)
};
app.UseRequestLocalization(localizationOptions);
app.UseAuthentication();
app.UseMvc();
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");
}
});
}
Identity Server Startup.cs
public void ConfigureServices(IServiceCollection services)
{
//var microsoftClientId = Configuration["MicrosoftClientId"];
// var microsoftClientSecret = Configuration["MircosoftClientSecret"];
var azureADClientId = Configuration["AzureADClientId"];
var azureADClientSecret = Configuration["AzureADClientSecret"];
var azureADEndPoint = Configuration["AzureADEndPoint"];
var issuerUri = Configuration["IssuerUri"];
string connectionString = Configuration.GetConnectionString("DefaultConnection");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext<IdentityServerDataContext>(options => options.UseSqlServer(connectionString));
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthentication()
// .AddCookie()
.AddOpenIdConnect("AAD", "Azure AD", options =>
{
options.Authority = string.Format("https://login.microsoftonline.com/{0}", azureADEndPoint);
options.ClientId = azureADClientId;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
});
IdentityModelEventSource.ShowPII = true;
services.AddTransient<IProfileService, IdentityWithAdditionalClaimsProfileService>();
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddIdentityServer() .AddSigninCredentialFromConfig(Configuration.GetSection("SigninKeyCredentials"), _logger)
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30;
})
.AddAspNetIdentity<ApplicationUser>()
.AddProfileService<IdentityWithAdditionalClaimsProfileService>();
}
// 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)
{
// this will do the initial DB population
// InitializeDatabase(app);
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentityServer();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Note: I only encounter this issue when I use the local login. It is working fine if I use the Azure AD login, I was able to connect to the API using the authorization token from the client app

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");
});