Skip to content

Commit

Permalink
Code style refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
lanedirt committed Jun 11, 2024
1 parent 638e8a4 commit d34b1ec
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 58 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
dotnet_diagnostic.SA1011.severity = none
dotnet_diagnostic.SA1101.severity = none
dotnet_diagnostic.SA1200.severity = none
dotnet_diagnostic.SA1309.severity = none
dotnet_diagnostic.SA1310.severity = warning
dotnet_diagnostic.SX1309.severity = none

# Razor files
[*.razor]
Expand Down
2 changes: 1 addition & 1 deletion src/AliasDb/AliasDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//-----------------------------------------------------------------------
namespace AliasDb;

using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

/// <summary>
/// The AliasDbContext class.
Expand Down
2 changes: 1 addition & 1 deletion src/AliasDb/AspNetUserRefreshTokens.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
//-----------------------------------------------------------------------
namespace AliasDb;

using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;

/// <summary>
/// Refresh tokens for users.
Expand Down
2 changes: 1 addition & 1 deletion src/AliasDb/Login.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
//-----------------------------------------------------------------------
namespace AliasDb;

using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;

/// <summary>
/// Login object.
Expand Down
1 change: 1 addition & 0 deletions src/AliasVault.Api/AliasVault.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>AliasVault.Api</RootNamespace>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
Expand Down
11 changes: 9 additions & 2 deletions src/AliasVault.Api/Controllers/AliasController.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
//-----------------------------------------------------------------------
// <copyright file="AliasController.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------

namespace AliasVault.Api.Controllers;

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using AliasDb;
using AliasVault.Shared.Models.WebApi;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Identity = AliasVault.Shared.Models.WebApi.Identity;
using Service = AliasVault.Shared.Models.WebApi.Service;
Expand Down
65 changes: 50 additions & 15 deletions src/AliasVault.Api/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
using System.Security.Cryptography;
using AliasDb;
using AliasVault.Shared.Models;
//-----------------------------------------------------------------------
// <copyright file="AuthController.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------

namespace AliasVault.Api.Controllers;

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using AliasDb;
using AliasVault.Shared.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;

/// <summary>
/// Auth controller for handling authentication.
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
Expand All @@ -19,9 +28,14 @@ public class AuthController : ControllerBase
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly IConfiguration _configuration;
private const string LoginProvider = "AliasVault";
private const string RefreshToken = "RefreshToken";

/// <summary>
/// Initializes a new instance of the <see cref="AuthController"/> class.
/// </summary>
/// <param name="context">AliasDbContext instance.</param>
/// <param name="userManager">UserManager instance.</param>
/// <param name="signInManager">SignInManager instance.</param>
/// <param name="configuration">IConfiguration instance.</param>
public AuthController(AliasDbContext context, UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager, IConfiguration configuration)
{
_context = context;
Expand All @@ -30,6 +44,11 @@ public AuthController(AliasDbContext context, UserManager<IdentityUser> userMana
_configuration = configuration;
}

/// <summary>
/// Login endpoint used to process login attempt using credentials.
/// </summary>
/// <param name="model">Login model.</param>
/// <returns>IActionResult.</returns>
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
Expand All @@ -39,9 +58,15 @@ public async Task<IActionResult> Login([FromBody] LoginModel model)
var tokenModel = await GenerateNewTokenForUser(user);
return Ok(tokenModel);
}

return Unauthorized();
}

/// <summary>
/// Refresh endpoint used to refresh an expired access token using a valid refresh token.
/// </summary>
/// <param name="tokenModel">Token model.</param>
/// <returns>IActionResult.</returns>
[HttpPost("refresh")]
public async Task<IActionResult> Refresh([FromBody] TokenModel tokenModel)
{
Expand Down Expand Up @@ -73,13 +98,13 @@ public async Task<IActionResult> Refresh([FromBody] TokenModel tokenModel)
var newRefreshToken = GenerateRefreshToken();

// Add new refresh token.
_context.AspNetUserRefreshTokens.Add(new AspNetUserRefreshToken
await _context.AspNetUserRefreshTokens.AddAsync(new AspNetUserRefreshToken
{
UserId = user.Id,
DeviceIdentifier = deviceIdentifier,
Value = newRefreshToken,
ExpireDate = DateTime.Now.AddDays(30),
CreatedAt = DateTime.Now
CreatedAt = DateTime.Now,
});
await _context.SaveChangesAsync();

Expand All @@ -88,6 +113,11 @@ public async Task<IActionResult> Refresh([FromBody] TokenModel tokenModel)

}

/// <summary>
/// Revoke endpoint used to revoke a refresh token.
/// </summary>
/// <param name="model">Token model.</param>
/// <returns>IActionResult.</returns>
[HttpPost("revoke")]
public async Task<IActionResult> Revoke([FromBody] TokenModel model)
{
Expand All @@ -97,7 +127,7 @@ public async Task<IActionResult> Revoke([FromBody] TokenModel model)
return Unauthorized("User not found (email-1)");
}

var user = await _userManager.FindByIdAsync(principal.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "");
var user = await _userManager.FindByIdAsync(principal.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty);
if (user == null)
{
return Unauthorized("User not found (email-2)");
Expand All @@ -118,6 +148,11 @@ public async Task<IActionResult> Revoke([FromBody] TokenModel model)
return Ok("Refresh token revoked successfully");
}

/// <summary>
/// Register endpoint used to register a new user.
/// </summary>
/// <param name="model">Register model.</param>
/// <returns>IActionResult.</returns>
[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegisterModel model)
{
Expand Down Expand Up @@ -146,7 +181,7 @@ private string GenerateJwtToken(IdentityUser user)
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Email, user.Email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
Expand Down Expand Up @@ -181,7 +216,7 @@ private ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])),
ValidateLifetime = false
ValidateLifetime = false,
};

var tokenHandler = new JwtSecurityTokenHandler();
Expand Down Expand Up @@ -219,13 +254,13 @@ private async Task<TokenModel> GenerateNewTokenForUser(IdentityUser user)
_context.AspNetUserRefreshTokens.RemoveRange(existingTokens);

// Add new refresh token.
_context.AspNetUserRefreshTokens.Add(new AspNetUserRefreshToken
await _context.AspNetUserRefreshTokens.AddAsync(new AspNetUserRefreshToken
{
UserId = user.Id,
DeviceIdentifier = deviceIdentifier,
Value = refreshToken,
ExpireDate = DateTime.Now.AddDays(30),
CreatedAt = DateTime.Now
CreatedAt = DateTime.Now,
});
await _context.SaveChangesAsync();

Expand Down
13 changes: 9 additions & 4 deletions src/AliasVault.Api/Controllers/AuthenticatedRequestController.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
//-----------------------------------------------------------------------
// <copyright file="AuthenticatedRequestController.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;

namespace AliasVault.Api.Controllers;

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace AliasVault.Api.Controllers;

[Route("api/[controller]")]
[ApiController]
Expand Down
18 changes: 15 additions & 3 deletions src/AliasVault.Api/Controllers/IdentityController.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
using AliasGenerators.Identity;
using AliasGenerators.Identity.Implementations;

//-----------------------------------------------------------------------
// <copyright file="IdentityController.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
namespace AliasVault.Api.Controllers;

using AliasGenerators.Identity;
using AliasGenerators.Identity.Implementations;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

/// <summary>
/// Controller for identity generation.
/// </summary>
public class IdentityController : AuthenticatedRequestController
{
/// <summary>
/// Initializes a new instance of the <see cref="IdentityController"/> class.
/// </summary>
/// <param name="userManager">UserManager instance.</param>
public IdentityController(UserManager<IdentityUser> userManager) : base(userManager)
{
}
Expand Down
57 changes: 26 additions & 31 deletions src/AliasVault.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
//-----------------------------------------------------------------------
// <copyright file="Program.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------

using System.Data.Common;
using System.Text;
using AliasDb;
Expand All @@ -14,9 +21,9 @@
builder.Services.AddLogging(logging =>
{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Debug); // Set the minimum level to Information
logging.AddFilter("Microsoft.AspNetCore.Identity.DataProtectorTokenProvider", LogLevel.Debug); // Ensure Identity logs are captured
logging.AddFilter("Microsoft.AspNetCore.Identity.UserManager", LogLevel.Debug); // Ensure Identity logs are captured
logging.SetMinimumLevel(LogLevel.Error);
logging.AddFilter("Microsoft.AspNetCore.Identity.DataProtectorTokenProvider", LogLevel.Error);
logging.AddFilter("Microsoft.AspNetCore.Identity.UserManager", LogLevel.Error);
});

// Add services to the container.
Expand All @@ -42,7 +49,7 @@
builder.Services.AddDataProtection();
builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromDays(30); // Set token lifespan for refresh tokens
options.TokenLifespan = TimeSpan.FromDays(30);
options.Name = "AliasVault";
});
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
Expand All @@ -57,8 +64,6 @@
options.Tokens.ProviderMap.Add("AliasVault", new TokenProviderDescriptor(typeof(DataProtectorTokenProvider<IdentityUser>)));
})
.AddEntityFrameworkStores<AliasDbContext>()
// Note: The AliasVault token provider is used to generate refresh tokens and is also defined
// in the AuthController.
.AddDefaultTokenProviders()
.AddTokenProvider<DataProtectorTokenProvider<IdentityUser>>("AliasVault");

Expand Down Expand Up @@ -86,7 +91,8 @@
// Configure CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
options.AddPolicy(
"CorsPolicy",
policy => policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
Expand All @@ -106,20 +112,22 @@
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
Scheme = "Bearer",
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
new OpenApiSecurityScheme
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer",
},
},
Array.Empty<string>()
},
Array.Empty<string>()
}});
});
});

var app = builder.Build();
Expand All @@ -144,23 +152,10 @@
var container = scope.ServiceProvider;
var db = container.GetRequiredService<AliasDbContext>();

db.Database.EnsureCreated();

/*if (!db..Any())
{
try
{
db.Initialize();
}
catch (Exception ex)
{
var logger = container.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the database. Error: {Message}", ex.Message);
}
}*/
await db.Database.EnsureCreatedAsync();
}

app.Run();
await app.RunAsync();

/// <summary>
/// For starting the WebAPI project in-memory from E2ETests project.
Expand Down

0 comments on commit d34b1ec

Please sign in to comment.