Skip to content

Instantly share code, notes, and snippets.

@shanji97
Created December 3, 2023 21:24
Show Gist options
  • Save shanji97/19022c72218e07e692667c1042223903 to your computer and use it in GitHub Desktop.
Save shanji97/19022c72218e07e692667c1042223903 to your computer and use it in GitHub Desktop.
Swagger issue.
using Carter;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using RSO.Core.BL;
using RSO.Core.Configurations;
using RSO.Core.Models;
using RSO.Core.Repository;
using System.Text;
using UserServiceRSO.Repository;
namespace UserServiceRSO;
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Register the IOptions object.
builder.Services.AddOptions<UserServicesSettingsConfiguration>()
.BindConfiguration("UserServicesSettingsConfiguration");
// Explicitly register the settings objects by delegating to the IOptions object.
builder.Services.AddSingleton(resolver => resolver.GetRequiredService<IOptions<UserServicesSettingsConfiguration>>().Value);
// Register the IOptions object.
builder.Services.AddOptions<JwtSecurityTokenConfiguration>()
.BindConfiguration("JwtSecurityTokenConfiguration");
// Explicitly register the settings objects by delegating to the IOptions object.
builder.Services.AddSingleton(resolver => resolver.GetRequiredService<IOptions<JwtSecurityTokenConfiguration>>().Value);
//Database settings
builder.Services.AddDbContext<UserServicesRSOContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("UserServicesRSOdB")));
//Lazy cache
builder.Services.AddLazyCache();
// Add unit of work & repositories.
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
builder.Services.AddScoped<IUserRepository, UserRepository>(); //In each microservice a different repository/serice is inlcuded. If more tables are needed add more repos related to the microservice.
// Logic
builder.Services.AddScoped<IUserLogic, UserLogic>(); //In each microservice a different repository/serice is inlcuded.
//JWT
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o => o.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
// Read from appsettings.json ...WARNING VALUES MUST BE THE SAME IN ALL IMPLEMENTATIONS.
// BETTER, CLEANER WAY?
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration
.GetSection("JwtSecurityTokenConfiguration").
Get<JwtSecurityTokenConfiguration>().SecretKey)),
ValidIssuer = builder.Configuration
.GetSection("JwtSecurityTokenConfiguration").
Get<JwtSecurityTokenConfiguration>().Issuer,
ValidAudience = builder.Configuration
.GetSection("JwtSecurityTokenConfiguration").
Get<JwtSecurityTokenConfiguration>().Audience
});
//Carter
builder.Services.AddHttpContextAccessor();
builder.Services.AddCarter();
// Add services to the container.
builder.Services.AddAuthorization();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(swagger =>
{
swagger.SwaggerDoc("v1", new OpenApiInfo()
{
Description = "User microservice for E-commerce app.",
Title = "RSO project.",
Version = "v1",
Contact = new OpenApiContact()
{
Name = "Aleksander Kovac & Urban Poljsak",
Url = new Uri("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
}
});
swagger.AddSecurityDefinition("jwt_auth", new OpenApiSecurityScheme()
{
Description = "Basic authorization with JWT token.",
Name = "Bearer",
BearerFormat ="JWT",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
swagger.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{new OpenApiSecurityScheme()
{
Reference = new OpenApiReference()
{
Id="jwt_auth",
Type = ReferenceType.SecurityScheme
}
},Array.Empty<string>() },
});
});
// APP.
var app = builder.Build();
// Carter
app.MapCarter();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "API"));
app.UseAuthentication();
app.UseAuthorization();
app.Run();
}
}
using Carter;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.HttpResults;
using RSO.Core.BL;
using RSO.Core.BL.LogicModels;
using RSO.Core.Models;
namespace UserServiceRSO.CarterModules;
public class UserEndpoints : ICarterModule
{
public void AddRoutes(IEndpointRouteBuilder app)
{
// Login and register options.
app.MapPost("/login", Login).WithName(nameof(Login)).
Produces(StatusCodes.Status200OK).
Produces(StatusCodes.Status400BadRequest);
app.MapPost("/register", Register).WithName(nameof(Register)).
Produces(StatusCodes.Status201Created).
Produces(StatusCodes.Status400BadRequest).
Produces(StatusCodes.Status404NotFound);
// Group for /api/user endpoinds.
var group = app.MapGroup("/api/user/");
// Methods for /api/user/id endpoints.
group.MapGet("{id}", GetUserById).WithName(nameof(GetUserById)).
Produces(StatusCodes.Status200OK).
Produces(StatusCodes.Status400BadRequest).
Produces(StatusCodes.Status401Unauthorized);
}
/// <summary>
/// Performs login and gets the JWT token.
/// </summary>
/// <param name="emailOrUsername"></param>
/// <param name="password"></param>
/// <param name="userLogic"></param>
/// <returns>A JWT token as a string.</returns>
public static async Task<Results<Ok<string>, BadRequest<string>>> Login(string emailOrUsername, string password, IUserLogic userLogic)
{
if (string.IsNullOrEmpty(emailOrUsername) || string.IsNullOrEmpty(password))
return TypedResults.BadRequest("Username (or email) and password cannot be null");
else
{
var user = await userLogic.GetUserByUsernameOrEmailAndPasswordAsync(emailOrUsername, password);
var jwt = userLogic.GetJwtToken(user);
return jwt is null
? TypedResults.BadRequest("The user with the specified username/email and password doesn't exist.")
: TypedResults.Ok(jwt);
}
}
/// <summary>
/// Performs registration and gets the JWT token.
/// </summary>
/// <param name="newUser">Data for the new user that is going to be created.</param>
/// <param name="userLogic">DI for B(usiness) L(logic) layer.</param>
/// <returns>A JWT token as a string.</returns>
public static async Task<Results<Created<string>, NotFound<string>, BadRequest<string>>> Register( User newUser, IUserLogic userLogic)
{
//SKIP VALIDATION (IMPLEMENT IT WHEN TIME REMAINS
newUser.UserCity = await userLogic.GetCityFromZipCodeAsync(newUser.UserZipCode);
newUser.UserZipCode = string.IsNullOrEmpty(newUser.UserCity) ? null : newUser.UserZipCode;
//Insert user and create a logic for the JWT
try
{
// Inser user into database
var user = await userLogic.RegisterUserAsync(newUser);
if (user is null) return TypedResults.NotFound("Something happened with the database that prevented the insertion of the user.");
// Generate a JWT token.
var jwt = userLogic.GetJwtToken(user);
return string.IsNullOrEmpty(jwt) ? TypedResults.BadRequest("User has been successfully registered but failed to retrieve the JWT token.") : TypedResults.Created("/", jwt);
}
catch (Exception ex)
{
return TypedResults.BadRequest(ex.Message);
}
}
/// <summary>
/// Gets the user by id.
/// </summary>
/// <param name="id">Id of the user.</param>
/// <param name="userLogic"><see cref="IUserLogic"/> instance.</param>
/// <returns>User data for the user.</returns>
[Authorize(AuthenticationSchemes = Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme)]
public static async Task<Results<Ok<UserDataDTO>, BadRequest<string>>> GetUserById(int id, IUserLogic userLogic)
{
/// Read the JWT token.
var user = await userLogic.GetUserByIdAsync(id);
if (user is null)
return TypedResults.BadRequest("User with the specified doesn't exist.");
var userData = new UserDataDTO(user);
return TypedResults.Ok(userData);
}
}
...
public string GetJwtToken(User existingUser)
{
var claims = new Claim[] {
new(JwtRegisteredClaimNames.Sub,existingUser.UserId.ToString()),
new(JwtRegisteredClaimNames.Email,existingUser.UserEmail),
new(JwtRegisteredClaimNames.AuthTime, DateTime.UtcNow.ToString()),
};
var signingCredentials = new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtConfiguration.SecretKey)),
SecurityAlgorithms.HmacSha256);
var jwtToken = new JwtSecurityToken(
_jwtConfiguration.Issuer,
_jwtConfiguration.Audience,
claims,
DateTime.UtcNow.AddSeconds(-5),
DateTime.UtcNow.AddDays(7),
signingCredentials);
return new JwtSecurityTokenHandler().WriteToken(jwtToken);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment