Code: Select all
Login.razor
Code: Select all
@page "/Account/Login"
@inject SignInManager SignInManager
@inject ILogger Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager
@inject IAuthService AuthService
Log in
Log in
Use a local account to log in.
@* Remember me *@
Log in
Forgot your password?
Register as a new user
Resend email confirmation
Use another service to log in.
@code {
private string? errorMessage;
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
[SupplyParameterFromForm]
private LoginRequestDto Input { get; set; } = new();
[SupplyParameterFromQuery]
private string? ReturnUrl { get; set; }
protected override async Task OnInitializedAsync()
{
if (HttpMethods.IsGet(HttpContext.Request.Method))
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
}
}
public async Task LoginUser()
{
await AuthService.Login(Input);
RedirectManager.RedirectTo(ReturnUrl);
}
}
< /code>
AuthService.cs
Code: Select all
public async Task Login(LoginRequestDto loginDto)
{
UserModel? userDb = default!;
if (!string.IsNullOrEmpty(loginDto.Email))
{
userDb = await _userManager.FindByEmailAsync(loginDto.Email);
}
else if (!string.IsNullOrEmpty(loginDto.UserName))
{
userDb = await _userManager.FindByNameAsync(loginDto.UserName);
}
if (userDb is null || !(await _signInManager.CheckPasswordSignInAsync(userDb, loginDto.Password, false)).Succeeded)
{
return null;
}
var result = await _signInManager.PasswordSignInAsync(userDb, loginDto.Password, false, false);
if (result.Succeeded)
{
var token = await GenerateAccessToken(userDb);
var response = userDb.ToAuthResponseDto(token);
return response;
}
return null;
}
< /code>
Program.cs
Code: Select all
var builder = WebApplication.CreateBuilder(args);
// Devlooped services
builder.Services.AddServices();
// Add services to the container.
// Ignore object cycling on queries with related data
builder.Services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
var securityScheme = new OpenApiSecurityScheme
{
Name = "JWT Authentication",
Description = "Enter your JWT token in this field",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
};
c.AddSecurityDefinition("Bearer", securityScheme);
var securityRequirement = new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer",
},
},
Array.Empty()
},
};
c.AddSecurityRequirement(securityRequirement);
});
builder.Services.AddRazorPages();
builder.Services.AddProblemDetails();
builder.Services.AddIdentity(options =>
{
options.SignIn.RequireConfirmedAccount = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireDigit = false;
options.Password.RequireUppercase = false;
options.User.RequireUniqueEmail = true;
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
})
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = builder.Configuration["JWT:Issuer"],
ValidateAudience = true,
ValidAudience = builder.Configuration["JWT:Audience"],
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(
System.Text.Encoding.UTF8.GetBytes(builder.Configuration["JWT:SignInKey"] !)),
};
options.IncludeErrorDetails = true;
});
builder.Services.ConfigureApplicationCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromHours(1);
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.Name = "APICOOKIE";
});
builder.Services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
IdentityConstants.ApplicationScheme,
JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
builder.Services.AddDbContextFactory(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddCors(options =>
{
options.AddPolicy("Default", policy =>
{
_ = policy.WithOrigins("https://localhost:7213")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
builder.Services.AddHttpContextAccessor();
var app = builder.Build();
app.UseCors();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
_ = app.UseSwagger();
_ = app.UseSwaggerUI();
// _ = app.MapControllers().AllowAnonymous();
}
app.Run();
< /code>
Program.cs
Code: Select all
var builder = WebApplication.CreateBuilder(args);
// Devlooped services
builder.Services.AddServices();
// Add MudBlazor services
builder.Services.AddMudServices();
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization(
options => options.SerializeAllClaims = true);
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddIdentity(options =>
{
options.SignIn.RequireConfirmedAccount = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireDigit = false;
options.Password.RequireUppercase = false;
options.User.RequireUniqueEmail = true;
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
})
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
});
builder.Services.ConfigureApplicationCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromHours(1);
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.None;
});
builder.Services.AddHttpClient("Auth", options =>
{
options.BaseAddress = new Uri(builder.Configuration["ApiUrl"]!);
}).AddHttpMessageHandler();
builder.Services.AddDbContextFactory(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
_ = app.UseMigrationsEndPoint();
} else
{
_ = app.UseExceptionHandler("/Error", createScopeForErrors: true);
// 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.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(SocialMedia.Front.Client._Imports).Assembly);
// Add additional endpoints required by the Identity /Account Razor components.
app.MapAdditionalIdentityEndpoints();
app.Run();
< /code>
Program.cs
Code: Select all
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// Devlooped services
builder.Services.AddServices();
builder.Services.AddMudServices();
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();
builder.Services.AddHttpClient("Auth", options =>
{
options.BaseAddress = new Uri(builder.Configuration["ApiUrl"]!);
}).AddHttpMessageHandler();
await builder.Build().RunAsync();
< /code>
PostsController.cs
Code: Select all
namespace SocialMedia.Api.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class PostsController(IPostService postService) : ControllerBase
{
private readonly string _postNotFoundMsg = "The post was not found!";
[HttpPost]
public async Task Create([FromBody] CreatePostRequestDto postToCreate)
{
var createdPost = await postService.Create(postToCreate);
if (createdPost == null)
{
return NotFound("User not found!");
}
return CreatedAtAction(
nameof(GetById),
new { createdPost.Id },
createdPost);
}
[HttpGet]
public async Task GetAll()
{
var posts = await postService.GetAll();
return Ok(posts);
}
[HttpGet("{id}")]
public async Task GetById([FromRoute] int id)
{
var post = await postService.GetById(id);
if (post == null)
{
return NotFound(_postNotFoundMsg);
}
return Ok(post);
}
[HttpPut]
public async Task Update([FromBody] UpdatePostRequestDto postToUpdate)
{
var updatedPost = await postService.Update(postToUpdate);
if (updatedPost == null)
{
return NotFound(_postNotFoundMsg);
}
return Ok(updatedPost);
}
[HttpDelete("{id}")]
public async Task Delete([FromRoute] int id)
{
var deletedPost = await postService.Delete(id);
if (deletedPost == null)
{
return NotFound(_postNotFoundMsg);
}
return NoContent();
}
}
}
< /code>
I saw that for cookies to be sent, it should have a CookieHander
Code: Select all
CookieHander.cs
Code: Select all
namespace SocialMedia.Front.Client.Middlewares
{
[Service(ServiceLifetime.Transient)]
public class CookieHandler : DelegatingHandler
{
protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
_ = request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
request.Headers.Add("X-Requested-With", ["XMLHttpRequest"]);
return await base.SendAsync(request, cancellationToken);
}
}
}
< /code>
Page printscreeen
Page printscreeen
I already tried using SignInManager