Reputation: 41
I'm building ASP .NET Core WebAPI application and trying to provide Token authentication to my app:
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(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer("Bearer", jwtBearerOptions =>
{
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
{
//ValidIssuer = "Issuer"
ValidateIssuer = false,
////ValidAudience = "WishlistAppClient",
//ValidateAudience = false,
////ClockSkew = TimeSpan.FromSeconds(5),
//ValidateLifetime = false,
//RequireExpirationTime = false,
//RequireSignedTokens = false,
};
});
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver()
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
services.AddDbContext<SchemaContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"), optionBuilder => optionBuilder.MigrationsAssembly("EventManager.DAL")
));
new DALRegistration().ConfigureServices(services);
var mappingConfig = new MapperConfiguration(configuration =>
{
configuration.AddProfile(new MappingProfile());
});
IMapper mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);
services
.AddIdentity<SystemUser, SystemRole>()
.AddEntityFrameworkStores<SchemaContext>()
.AddDefaultTokenProviders();
services.AddScoped<IUserManager, UserManager>();
services.AddScoped<ILoginProvider, LoginProvider>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
c.DescribeAllEnumsAsStrings();
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/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.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
var todayDate = DateTime.Now.ToShortDateString().Replace('/', '.');
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
c.DocExpansion(DocExpansion.None);
});
loggerFactory.AddFile(Path.Combine(Directory.GetCurrentDirectory(), "LogInformation", $"{DateTime.Now.ToShortDateString().Replace('/','.')}.txt"));
var logger = loggerFactory.CreateLogger("New Logger");
app.Use(async (context, next) =>
{
logger.LogTrace("Processing request {0}", context.Request.Path);
await next.Invoke();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
spa.Options.StartupTimeout = new TimeSpan(0, 2, 0);
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
API Code is protected by [Authorize(AuthenticationSchemes = "Bearer")] When I send request with any token, I always receive 401. The trouble is, that i turned off all token validation, but it does not help.
There is a picture of request in Postman
Response body is empty. Response headers(if you can't load image):
Request:
Upvotes: 4
Views: 9511
Reputation: 194
Here is an example to of how I've implemented
services.AddAuthentication()
.AddCookie()
.AddJwtBearer(cfg =>
{
cfg.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
};
});
and on the controller, similar to yours
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
In the authentication controller, which is called by Login page with credentials. You have to implement the below code after checking if the username and password is correct
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Email),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
_config["Tokens:Issuer"],
_config["Tokens:Audience"],
claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
var results = new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
};
Upvotes: 2