Created JWT endpoints

This commit is contained in:
2026-02-21 19:35:55 +01:00
parent 1c0fc26f7e
commit 9740d92cbf
8 changed files with 140 additions and 7 deletions
-1
View File
@@ -27,7 +27,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="DTO\Auth\" />
<Folder Include="DTO\Friends\" />
<Folder Include="DTO\Groups\" />
<Folder Include="DTO\Messages\" />
+6
View File
@@ -0,0 +1,6 @@
namespace BeReadyBackend.DTO.Auth;
public class GetTokenDto
{
public string? Token { get; set; }
}
+7
View File
@@ -0,0 +1,7 @@
namespace BeReadyBackend.DTO.Auth;
public class LoginDto
{
public string? Username { get; set; }
public string? Password { get; set; }
}
@@ -0,0 +1,6 @@
namespace BeReadyBackend.DTO.Auth;
public class RefreshTokenDto
{
public string? Token { get; set; }
}
@@ -0,0 +1,44 @@
using BeReadyBackend.DTO.Auth;
using BeReadyBackend.Models;
using BeReadyBackend.Repositories;
using BeReadyBackend.Specifications.Users;
using FastEndpoints;
using FastEndpoints.Security;
namespace BeReadyBackend.Endpoints.Auth;
public class LoginEndpoint(UsersRepository usersRepository, AutoMapper.IMapper mapper) : Endpoint<LoginDto, GetTokenDto>
{
public override void Configure()
{
Post("/Auth/Login");
AllowAnonymous();
}
public override async Task HandleAsync(LoginDto req, CancellationToken ct)
{
User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByUsernameSpec(req.Username!), ct);
if (user == null)
{
await Send.UnauthorizedAsync(ct);
return;
}
if (BCrypt.Net.BCrypt.Verify(req.Password + user.Salt, user.Password))
{
string jwtToken = JwtBearer.CreateToken(o =>
{
o.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong";
o.ExpireAt = DateTime.UtcNow.AddDays(15);
o.User.Claims.Add(("Username", user.Username)!);
o.User.Claims.Add(("FullName", user.FirstName + user.Name));
o.User.Claims.Add(("UserId", user.Id.ToString()));
}
);
await Send.OkAsync(new GetTokenDto { Token = jwtToken }, ct);
}
else await Send.UnauthorizedAsync(ct);
}
}
@@ -0,0 +1,58 @@
using System.IdentityModel.Tokens.Jwt;
using BeReadyBackend.DTO.Auth;
using BeReadyBackend.Models;
using BeReadyBackend.Repositories;
using BeReadyBackend.Specifications.Users;
using FastEndpoints;
using FastEndpoints.Security;
namespace BeReadyBackend.Endpoints.Auth;
public class RefreshTokenEndpoint(UsersRepository usersRepository, AutoMapper.IMapper mapper) : Endpoint<RefreshTokenDto, GetTokenDto>
{
public override void Configure()
{
Post("/Auth/RefreshToken");
AllowAnonymous();
}
public override async Task HandleAsync(RefreshTokenDto req, CancellationToken ct)
{
try
{
JwtSecurityTokenHandler handler = new();
JwtSecurityToken? token = handler.ReadJwtToken(req.Token);
string? username = token.Claims.FirstOrDefault(c => c.Type == "Username")?.Value;
if (string.IsNullOrWhiteSpace(username))
{
await Send.UnauthorizedAsync(ct);
return;
}
User? user = await usersRepository.FirstOrDefaultAsync(new GetUserByUsernameSpec(username), ct);
if (user is null)
{
await Send.UnauthorizedAsync(ct);
return;
}
string jwtToken = JwtBearer.CreateToken(o =>
{
o.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong";
o.ExpireAt = DateTime.UtcNow.AddDays(15);
o.User.Claims.Add(("Username", user.Username)!);
o.User.Claims.Add(("FullName", user.FirstName + user.Name));
o.User.Claims.Add(("UserId", user.Id.ToString()));
}
);
await Send.OkAsync(new GetTokenDto { Token = jwtToken }, ct);
}
catch
{
await Send.UnauthorizedAsync(ct);
}
}
}
+6 -6
View File
@@ -15,10 +15,6 @@ builder.Services
.AddAuthenticationJwtBearer(s => s.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong")
.AddAuthorization()
.AddFastEndpoints()
.SwaggerDocument(options =>
{
options.ShortSchemaNames = true;
})
.AddCors(options =>
{
options.AddDefaultPolicy(policyBuilder =>
@@ -29,6 +25,10 @@ builder.Services
.AllowAnyHeader()
.WithExposedHeaders(HeaderNames.ContentDisposition);
});
})
.SwaggerDocument(options =>
{
options.ShortSchemaNames = true;
});
builder.Services.AddDbContext<BeReadyDbContext>();
@@ -65,8 +65,8 @@ app.UseAuthentication()
})
.UseSwaggerGen();
app.UseHttpsRedirection();
// app.UseHttpsRedirection();
app.UseCors();
// app.UseCors();
app.Run();
@@ -0,0 +1,13 @@
using Ardalis.Specification;
using BeReadyBackend.Models;
namespace BeReadyBackend.Specifications.Users;
public class GetUserByUsernameSpec : SingleResultSpecification<User>
{
public GetUserByUsernameSpec(string username)
{
Query
.Where(x => x.Username == username);
}
}