diff --git a/Controllers/ContactQueueCreationController.cs b/Controllers/ContactQueueCreationController.cs index 0cfe19a..a6af7ad 100644 --- a/Controllers/ContactQueueCreationController.cs +++ b/Controllers/ContactQueueCreationController.cs @@ -1,7 +1,9 @@ +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace TextSender_API.Controllers; +[Authorize] [ApiController] [Route("api/v1/contact/queue")] public class ContactQueueCreationController : ControllerBase diff --git a/Controllers/UsersController.cs b/Controllers/UsersController.cs index 01625e0..c90b7aa 100644 --- a/Controllers/UsersController.cs +++ b/Controllers/UsersController.cs @@ -1,6 +1,13 @@ +using System.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; using System.Linq; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; +using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using TextSender_API.Models; @@ -28,6 +35,53 @@ public class UsersController : ControllerBase #endregion #region Methods + private string AllScopes() + { + var allScopes = new List() + { + "create:contact" + }; + + var scopes = string.Empty; + + for (var i = 0; i < allScopes.Count; i++) + { + if (i == allScopes.Count - 1) + { + scopes += allScopes[i]; + } + else + { + scopes += allScopes[i] + " "; + } + } + + return scopes; + } + + private List Payload() + { + var expLimit = 30; + var currentDate = DateTime.Now; + var expiredDate = currentDate.AddMinutes(expLimit); + var issued = Math.Floor((currentDate - DateTime.UnixEpoch).TotalSeconds); + var expires = Math.Floor((expiredDate - DateTime.UnixEpoch).TotalSeconds); + var issuer = this._config["JWT:Issuer"]; + var audience = this._config["JWT:Audience"]; + var subject = this._config["JWT:Subject"]; + + var claim = new List() + { + new System.Security.Claims.Claim("scope", AllScopes(), "string"), + new System.Security.Claims.Claim(JwtRegisteredClaimNames.Exp, expiredDate.ToString(), "string"), + new System.Security.Claims.Claim(JwtRegisteredClaimNames.Aud, audience!), + new System.Security.Claims.Claim(JwtRegisteredClaimNames.Iss, issuer!), + new Claim(JwtRegisteredClaimNames.Sub, subject!) + }; + + return claim; + } + [HttpPost("login")] public IActionResult Login([FromBody] User userRequest) { @@ -43,11 +97,37 @@ public class UsersController : ControllerBase if (result.Item1 && pwdVerify.VerifyPassword(result.Item2, userRequest.Password!)) { + var user = result.Item2; var token = new Token(); - // TODO: Generate access token - token.AccessToken = string.Empty; token.Issued = DateTime.Now; - token.UserId = result.Item2.Id; + token.UserId = user.Id; + token.TokenType = "JWT"; + + var payload = Payload(); + payload.Add(new System.Security.Claims.Claim("user_id", user.Id!, ClaimValueTypes.String)); + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this._config["JWT:Secret"]!)); + var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + + var tok = new JwtSecurityToken( + this._config["JWT:Issuer"], + this._config["JWT:Audience"], + payload, + expires: DateTime.UtcNow.AddMinutes(30), + signingCredentials: signIn); + + token.AccessToken = new JwtSecurityTokenHandler().WriteToken(tok); + + var expClaim = payload.FirstOrDefault(cl => + { + return cl.Type.Equals("exp"); + }); + + if (expClaim != null) + { + var expiredDate = DateTime.Parse(expClaim!.Value); + var exp = Math.Floor((expiredDate - DateTime.UnixEpoch).TotalSeconds); + } response.Data.Add(token); Ok(response); diff --git a/Models/Token.cs b/Models/Token.cs index 2e2adaf..afbe858 100644 --- a/Models/Token.cs +++ b/Models/Token.cs @@ -7,6 +7,8 @@ public class Token #region Properties [JsonProperty("access_token")] public string? AccessToken { get; set; } + [JsonProperty("token_type")] + public string? TokenType { get; set; } [JsonProperty("issued")] public DateTime? Issued { get; set; } [JsonProperty("id")] diff --git a/Program.cs b/Program.cs index d22fd0b..dcd5257 100644 --- a/Program.cs +++ b/Program.cs @@ -1,10 +1,10 @@ using System.Text; -using Microsoft.IdentityModel.Tokens; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.IdentityModel.Tokens; var builder = WebApplication.CreateBuilder(args); @@ -17,10 +17,6 @@ builder.Services.AddControllers().AddNewtonsoftJson(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); -var app = builder.Build(); - -var connString = builder.Configuration.GetConnectionString("DefaultConnection"); - builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { options.RequireHttpsMetadata = false; @@ -31,10 +27,16 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJw ValidateAudience = true, ValidAudience = builder.Configuration["JWT:Audience"], ValidIssuer = builder.Configuration["JWT:Issuer"], + RequireExpirationTime = false, + ValidateIssuerSigningKey = false, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:Secret"]!)) }; }); +var app = builder.Build(); + +var connString = builder.Configuration.GetConnectionString("DefaultConnection"); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { @@ -46,8 +48,13 @@ if (app.Environment.IsDevelopment()) app.UseHttpsRedirection(); app.UseAuthentication(); +app.UseRouting(); app.UseAuthorization(); +app.UseEndpoints(endpoints => +{ + endpoints.MapControllers(); +}); -app.MapControllers(); +// app.MapControllers(); app.Run();