following this tutorialI've encountered a problem in the Startup.cs file:
(need to scroll down a bit, sorry)
the issue is with default identity, getting the following error:
"IServiceCollection does not contain a definition for AddDefaultIdentity and no accessible extension method AddDefaultIdentity accepting a first argument of type" IServiceCollection could be found(are you missing a using directive or an assembly reference?)"
I looked up the documentation, but I'm missing what error I'm making, I've seen a bunch of cases similar to mine, but their solution (included) doesn't seems to work. I can us some help, thanks in advance.
"my" code is HERE if you want to take a look
You shouldn't add identity if you use Jwt autentication...Note: AddDefaultIdentity extension method is used to add the default UI service for Razor Pages and MVC. And it also requires you to add StaticFiles.
Note also the additional code and its arrangement in the Configure method
Try this in your startup class:
public class Startup
{
//add
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddNewtonsoftJson();
services.AddTransient<IJwtTokenService, JwtTokenService>();
//Setting up Jwt Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
};
});
services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "application/octet-stream" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseResponseCompression();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBlazorDebugging();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(routes =>
{
routes.MapDefaultControllerRoute();
});
app.UseBlazor<Client.Startup>();
}
}
}
Hope this helps...
Update 1: * Update your Startup class with the code above * Annotate your SampleDataController controller like this:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/[controller]")]
public class SampleDataController : Controller
{
// ..
}
api/SampleData/WeatherForecasts
The response should contain the created JwtToken
Summary of the flow of execution: Posting a get request to your Web Api. The request to the route point WeatherForecasts is redirected to the Token controller whose purpose is to create a Jwt token and return it to the caller. Note that this controller does not verify the identity of the the user on whose behalf this request was send...
TO DO:
Note: That you may pass the Jwt Token from the server to Blazor with more details about the user as a cookie.
Note: If the user is already authenticated, he's not redirected to the Login form. Instead we issue an http request to the server, in order to retrieve the rsources needed in Blazor, if that is the case.
Note: How do we know if our user is authenticated ? We query our IsAutenticated method. If the user is authenticated, if retrieve the Jwt Token and add it to the headers collection passed with our HttpClient call.
More to come...
Do you see it ?