Created JWT endpoints
This commit is contained in:
@@ -27,7 +27,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="DTO\Auth\" />
|
||||
<Folder Include="DTO\Friends\" />
|
||||
<Folder Include="DTO\Groups\" />
|
||||
<Folder Include="DTO\Messages\" />
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace BeReadyBackend.DTO.Auth;
|
||||
|
||||
public class GetTokenDto
|
||||
{
|
||||
public string? Token { get; set; }
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user