Convert DateTime to ISO 8601 Date in string format in C#
DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture);
To get the specified format, you can use:
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)
DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture);
To get the specified format, you can use:
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)
Chrony is an implementation of the Network Time Protocol (NTP) that runs on Unix-like operating systems (including Linux and macOS) and is released under the GNU GPL v2. It can synchronize the system clock with NTP servers, reference clocks (e.g. GPS receiver), and manual input using wristwatch and keyboard. It can also operate as an NTPv4 (RFC 5905) server and peer to provide a time service to other computers in the network.
apt install -y chrony timedatectl set-ntp true systemctl enable chrony && systemctl restart chrony timedatectl set-timezone Asia/Tehran chronyc sourcestats -v chronyc tracking -v date
References
https://installati.one/install-chrony-ubuntu-22-04/
services.AddCors(options => { options.AddDefaultPolicy(builder => { builder.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod(); }); });
app.UseCors();
References
https://stacktuts.com/how-to-enable-cors-in-asp-net-core-6-0-web-api-project
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-7.0
[HttpPost("refresh-token")] public async Task<ActionResult<string>> RefreshToken() { var refreshToken = Request.Cookies["refreshToken"]; if (!user.RefreshToken.Equals(refreshToken)) { return Unauthorized("Invalid Refresh Token."); } else if(user.TokenExpires < DateTime.Now) { return Unauthorized("Token expired."); } string token = CreateToken(user); var newRefreshToken = GenerateRefreshToken(); SetRefreshToken(newRefreshToken); return Ok(token); } private RefreshToken GenerateRefreshToken() { var refreshToken = new RefreshToken { Token = Convert.ToBase64String(RandomNumberGenerator.GetBytes(64)), Expires = DateTime.Now.AddDays(7), Created = DateTime.Now }; return refreshToken; } private void SetRefreshToken(RefreshToken newRefreshToken) { var cookieOptions = new CookieOptions { HttpOnly = true, Expires = newRefreshToken.Expires }; Response.Cookies.Append("refreshToken", newRefreshToken.Token, cookieOptions); user.RefreshToken = newRefreshToken.Token; user.TokenCreated = newRefreshToken.Created; user.TokenExpires = newRefreshToken.Expires; }
References
https://www.youtube.com/watch?v=HGIdAn2h8BA
https://www.youtube.com/watch?v=LowJMwa7LCU
https://passage.id/post/how-refresh-tokens-work-a-complete-guide-for-beginners?utm_source=pocket_reader
https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/?utm_source=pocket_reader
var stream = "[encoded jwt]"; var handler = new JwtSecurityTokenHandler(); var jsonToken = handler.ReadToken(stream); var tokenS = jsonToken as JwtSecurityToken;
Or, without the cast:
var token = "[encoded jwt]"; var handler = new JwtSecurityTokenHandler(); var jwtSecurityToken = handler.ReadJwtToken(token);
I can get Claims using:
var jti = tokenS.Claims.First(claim => claim.Type == "jti").Value;
References
https://stackoverflow.com/questions/38340078/how-to-decode-jwt-token?utm_source=pocket_reader
ASP.NET Core interface IHostApplicationLifetime
allows developers to subscribe their handlers to ApplicationStarted, ApplicationStopping and ApplicationStopped events
ASP.NET Core provides developers with an IHostedService
interface that has StartAsync
and StopAsync
methods that are executed when the application starts and stops. This interface is typically used to trigger long running background tasks, but StartAsync
itself must return quickly so as not to block other hosted services, if any.
public class EInvoiceSenderService: IHostedService { private readonly ILogger logger; private readonly IHostApplicationLifetime appLifetime; public EInvoiceSenderService( ILogger<LifetimeEventsHostedService> logger, IHostApplicationLifetime appLifetime) { //<--- INJECTED DEPENDENCY this.logger = logger; this.appLifetime = appLifetime; } public Task StartAsync(CancellationToken cancellationToken) { appLifetime.ApplicationStarted.Register(OnStarted); appLifetime.ApplicationStopping.Register(OnStopping); appLifetime.ApplicationStopped.Register(OnStopped); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } private void OnStarted() { logger.LogInformation("OnStarted has been called."); // Perform post-startup activities here } private void OnStopping() { logger.LogInformation("OnStopping has been called."); // Perform on-stopping activities here } private void OnStopped() { logger.LogInformation("OnStopped has been called."); // Perform post-stopped activities here } }
Program.cs
builder.Services.AddHostedService<EInvoiceSenderService>();
References
https://levelup.gitconnected.com/3-ways-to-run-code-once-at-application-startup-in-asp-net-core-bcf45a6b6605
https://stackoverflow.com/questions/59650230/how-to-get-and-inject-the-ihostapplicationlifetime-in-my-service-to-the-containe
[HttpGet] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public async Task<ActionResult<string>> Get() { var token = await HttpContext.GetTokenAsync("access_token"); return token; }
var token = Request.Headers["Authorization"];
var token2 = await HttpContext.GetTokenAsync(JwtBearerDefaults.AuthenticationScheme, "access_token");
References
https://stackoverflow.com/questions/58887151/how-to-access-token-data-from-controller-method
https://stackoverflow.com/questions/52793488/jwt-cannot-be-retrieved-by-httpcontext-gettokenasync-in-net-core-2-1
[HttpGet("me"), Authorize] public async Task<ActionResult<ResponseDto<GetMeResponseDto>>> GetMe() { try { ResponseDto<GetMeResponseDto> result = new(); var cts = new CancellationTokenSource(); var context = await _dbFactory.CreateDbContextAsync(cts.Token); var userName = User?.Identity?.Name; if (!string.IsNullOrEmpty(userName)) { var user = await context.Users.FirstOrDefaultAsync(x => x.Username == userName, cancellationToken: cts.Token); if (user != null) { var role = User!.FindFirstValue(ClaimTypes.Role) ?? string.Empty; result.Data = new GetMeResponseDto() { Id = user.Id, Username = userName, Role = role, }; result.HasError = false; } } return Ok(result); } catch (Exception e) { _logger.LogErrorEx(e, e.Message); } return BadRequest(); }
Or you can use HttpContext
to access it.
References
https://www.youtube.com/watch?v=fhWIkbF18lM
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-7.0
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/use-http-context?view=aspnetcore-7.0
https://www.youtube.com/watch?v=7vqAHD9DlIA
Add Nuget Packages
Microsoft.AspNetCore.Authentication.JwtBearer Microsoft.IdentityModel.Tokens System.IdentityModel.Tokens.Jwt
Add setting in appsetting.json
"Jwt": { "Key": "ACDt1vR3lXToPQ1g3MyN", //Generate random String from https://www.random.org/strings "Issuer": "http://localhost:28747/", //Project Property-> Debug-> IIS-->App URL (you can local host url as well) "Audience": "http://localhost:28747/" },
Register JWT token for Authentication in Program.cs file
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //JWT Authentication builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
Create Models (UserLogin, UserModel and UserConstant)
namespace JWTLoginAuthenticationAuthorization.Models { public class UserModel { public string Username { get; set; } public string Password { get; set; } public string Role { get; set; } } }
namespace JWTLoginAuthenticationAuthorization.Models { public class UserLogin { public string Username { get; set; } public string Password { get; set; } } }
namespace JWTLoginAuthenticationAuthorization.Models { // We are not taking data from data base so we get data from constant public class UserConstants { public static List<UserModel> Users = new() { new UserModel(){ Username="naeem",Password="naeem_admin",Role="Admin"} }; } }
Create LoginAPI Controller (Authenticate user and generate token)
using JWTLoginAuthenticationAuthorization.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; namespace JWTLoginAuthenticationAuthorization.Controllers { [Route("api/[controller]")] [ApiController] public class LoginController : ControllerBase { private readonly IConfiguration _config; public LoginController(IConfiguration config) { _config = config; } [AllowAnonymous] [HttpPost] public ActionResult Login([FromBody] UserLogin userLogin) { var user = Authenticate(userLogin); if (user != null) { var token = GenerateToken(user); return Ok(token); } return NotFound("user not found"); } // To generate token private string GenerateToken(UserModel user) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var claims = new[] { new Claim(ClaimTypes.NameIdentifier,user.Username), new Claim(ClaimTypes.Role,user.Role) }; var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Audience"], claims, expires: DateTime.Now.AddMinutes(15), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); } //To authenticate user private UserModel Authenticate(UserLogin userLogin) { var currentUser = UserConstants.Users.FirstOrDefault(x => x.Username.ToLower() == userLogin.Username.ToLower() && x.Password == userLogin.Password); if (currentUser != null) { return currentUser; } return null; } } }
Create User API Controller to authorize user role
namespace JWTLoginAuthenticationAuthorization.Controllers { [Route("api/[controller]")] [ApiController] public class UserController : ControllerBase { //For admin Only [HttpGet] [Route("Admins")] [Authorize(Roles = "Admin")] public IActionResult AdminEndPoint() { var currentUser = GetCurrentUser(); return Ok($"Hi you are an {currentUser.Role}"); } private UserModel GetCurrentUser() { var identity = HttpContext.User.Identity as ClaimsIdentity; if (identity != null) { var userClaims = identity.Claims; return new UserModel { Username = userClaims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value, Role = userClaims.FirstOrDefault(x => x.Type == ClaimTypes.Role)?.Value }; } return null; } } }
References
https://www.c-sharpcorner.com/article/jwt-token-creation-authentication-and-authorization-in-asp-net-core-6-0-with-po/
https://www.youtube.com/watch?v=UwruwHl3BlU
https://www.youtube.com/watch?v=6sMPvucWNRE
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Once rebooted, open the Windows App store and search for the “Kali Linux” application, or alternatively click here to go there directly. Install the app and enjoy Kali!
Install Kali Linux Metapackages
sudo apt update sudo apt full-upgrade -y
sudo apt install -y kali-linux-default
Install Win-KeX
Win-KeX provides a Kali Desktop Experience for Windows Subsystem for Linux (WSL 2)
sudo apt update sudo apt install -y kali-win-kex
To start Win-KeX in Window mode with sound support, run
kex --win -s
To start Win-KeX in Enhanced Session Mode with sound support and arm workaround, run
kex --esm --ip -s
To start Win-KeX in Seamless mode with sound support, run
kex --sl -s
Optional Steps
If you have the space, why not install “Kali with the lot”?
sudo apt install -y kali-linux-large
References
https://www.kali.org/blog/kali-linux-in-the-windows-app-store/
https://www.kali.org/docs/general-use/metapackages/
https://www.kali.org/docs/wsl/win-kex/