Skip to content

Commit dcd0e38

Browse files
committed
chore(*): finish up auth, add services
1 parent e64259c commit dcd0e38

File tree

10 files changed

+175
-4
lines changed

10 files changed

+175
-4
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Micro.AppRegistration.Api.Auth
2+
{
3+
public class CustomClaims
4+
{
5+
public const string Permission = "Permission";
6+
}
7+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Linq;
3+
using Microsoft.AspNetCore.Authorization;
4+
using Microsoft.AspNetCore.Mvc;
5+
using Microsoft.AspNetCore.Mvc.Filters;
6+
7+
namespace Micro.AppRegistration.Api.Auth
8+
{
9+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
10+
public class RequirePermission : Attribute, IAuthorizeData, IAuthorizationFilter
11+
{
12+
public string AuthenticationSchemes { get; set; }
13+
public string Policy { get; set; }
14+
public string Roles { get; set; }
15+
private readonly string _permission;
16+
17+
public RequirePermission(string permission)
18+
{
19+
_permission = permission;
20+
}
21+
22+
public void OnAuthorization(AuthorizationFilterContext context)
23+
{
24+
var permissionClaims = context.HttpContext?.User?.Claims?.Where(c => c.Type == CustomClaims.Permission);
25+
var hasClaim = permissionClaims?.Any(x => x.Value == _permission || x.Value == "sudo");
26+
if (!hasClaim.HasValue || !hasClaim.Value)
27+
{
28+
context.Result = new ForbidResult();
29+
}
30+
}
31+
}
32+
}
Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Micro.AppRegistration.Api.UserDataExtensions;
4+
using Microsoft.AspNetCore.Authorization;
5+
using Microsoft.AspNetCore.Http;
16
using Microsoft.AspNetCore.Mvc;
27

38
namespace Micro.AppRegistration.Api.CreateApplication
@@ -6,6 +11,29 @@ namespace Micro.AppRegistration.Api.CreateApplication
611
[Route("api/[controller]")]
712
public class AppRegistrationController : ControllerBase
813
{
9-
14+
private readonly IAppRegistrationService _appRegistrationService;
15+
16+
public AppRegistrationController(IAppRegistrationService appRegistrationService)
17+
{
18+
_appRegistrationService = appRegistrationService;
19+
}
20+
21+
[HttpPost]
22+
[Authorize]
23+
public async Task<IActionResult> Test(CreateApplicationRequest request)
24+
{
25+
try
26+
{
27+
var application = await _appRegistrationService.CreateApplication(request, this.GetUserId());
28+
return Ok(application);
29+
}
30+
catch (Exception e)
31+
{
32+
return StatusCode(StatusCodes.Status500InternalServerError, new ProblemDetails
33+
{
34+
Title = "internal server error"
35+
});
36+
}
37+
}
1038
}
1139
}

Micro.AppRegistration.Api/CreateApplication/AppRegistrationService.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
using System;
2+
using System.Security.Cryptography;
13
using System.Threading.Tasks;
24
using Micro.AppRegistration.Api.Models;
5+
using Micro.AppRegistration.Api.Uuid;
6+
using Microsoft.AspNetCore.Identity;
37

48
namespace Micro.AppRegistration.Api.CreateApplication
59
{
@@ -10,9 +14,45 @@ public interface IAppRegistrationService
1014

1115
public class AppRegistrationService : IAppRegistrationService
1216
{
17+
private readonly IPasswordHasher<Application> _hasher;
18+
private readonly ICreateApplicationRepository _applicationRepository;
19+
20+
public AppRegistrationService(IPasswordHasher<Application> hasher, ICreateApplicationRepository applicationRepository)
21+
{
22+
_hasher = hasher;
23+
_applicationRepository = applicationRepository;
24+
}
25+
1326
public async Task<Application> CreateApplication(CreateApplicationRequest request, string userId)
1427
{
15-
throw new System.NotImplementedException();
28+
var secret = GenerateApplicationSecret();
29+
var hashedSecret = _hasher.HashPassword(null, secret);
30+
var application = await _applicationRepository.Create(new Application
31+
{
32+
Approved = false,
33+
Name = request.Name,
34+
Secret = hashedSecret,
35+
User = userId,
36+
CreatedBy = userId,
37+
UseDefaultCode = request.UseDefault,
38+
ShortCode = request.ShortCode
39+
});
40+
application.Secret = secret;
41+
return application;
42+
}
43+
44+
private static string GenerateApplicationSecret()
45+
{
46+
return Convert.ToBase64String(GenerateRandomBytes(256));
47+
}
48+
49+
private static byte[] GenerateRandomBytes(int keyBitLength)
50+
{
51+
using var provider = new RNGCryptoServiceProvider();
52+
var lengthInByte = keyBitLength / 8;
53+
var randomNumber = new byte[lengthInByte];
54+
provider.GetBytes(randomNumber);
55+
return randomNumber;
1656
}
1757
}
1858
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Micro.AppRegistration.Api.Models;
4+
using Micro.AppRegistration.Api.Uuid;
5+
6+
namespace Micro.AppRegistration.Api.CreateApplication
7+
{
8+
public interface ICreateApplicationRepository
9+
{
10+
public Task<Application> Create(Application application);
11+
}
12+
public class CreateApplicationRepository : ICreateApplicationRepository
13+
{
14+
private readonly ApplicationContext _applicationContext;
15+
private readonly IUuidService _uuidService;
16+
17+
public CreateApplicationRepository(ApplicationContext applicationContext, IUuidService uuidService)
18+
{
19+
_applicationContext = applicationContext;
20+
_uuidService = uuidService;
21+
}
22+
23+
public async Task<Application> Create(Application application)
24+
{
25+
var result = await _applicationContext.Applications.AddAsync(new Application
26+
{
27+
Id = _uuidService.GenerateUuId(),
28+
User = application.User,
29+
Approved = application.Approved,
30+
Name = application.Name,
31+
Secret = application.Secret,
32+
CreatedAt = DateTime.Now,
33+
CreatedBy = application.CreatedBy,
34+
ShortCode = application.ShortCode,
35+
UseDefaultCode = application.UseDefaultCode
36+
});
37+
await _applicationContext.SaveChangesAsync();
38+
return result.Entity;
39+
}
40+
}
41+
}

Micro.AppRegistration.Api/Startup.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public void ConfigureServices(IServiceCollection services)
2929
services.AddControllers();
3030
services.ConfigureSwagger();
3131
services.RegisterWorker();
32+
services.ConfigureIdentityServices(Configuration);
3233
}
3334

3435
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -40,6 +41,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerF
4041
app.UseDeveloperExceptionPage();
4142
}
4243
app.UseRouting();
44+
app.UseAuthentication();
4345
app.UseAuthorization();
4446
app.AddSwaggerWithUi();
4547
app.UseEndpoints(endpoints =>

Micro.AppRegistration.Api/StartupExtensions/DependencyInjection.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
using Fossapps.Micro.KeyStore;
33
using Micro.AppRegistration.Api.Auth;
44
using Micro.AppRegistration.Api.Configs;
5+
using Micro.AppRegistration.Api.CreateApplication;
56
using Micro.AppRegistration.Api.Models;
67
using Micro.AppRegistration.Api.Uuid;
8+
using Microsoft.AspNetCore.Identity;
79
using Microsoft.Extensions.Configuration;
810
using Microsoft.Extensions.DependencyInjection;
911

@@ -16,6 +18,9 @@ public static void ConfigureRequiredDependencies(this IServiceCollection service
1618
services.AddDbContext<ApplicationContext>();
1719
services.AddSingleton<IUuidService, UuidService>();
1820
services.AddSingleton<IKeyResolver, KeyResolver>();
21+
services.AddScoped<IAppRegistrationService, AppRegistrationService>();
22+
services.AddScoped<ICreateApplicationRepository, CreateApplicationRepository>();
23+
services.AddSingleton<IPasswordHasher<Application>, PasswordHasher<Application>>();
1924
services.AddSingleton(SetupKeyStoreHttpClient(configuration.GetSection("Services").Get<Services>().KeyStore));
2025
}
2126

Micro.AppRegistration.Api/StartupExtensions/Identity.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ public static void ConfigureIdentityServices(this IServiceCollection serviceColl
1919
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
2020
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
2121
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
22-
}).AddJwtBearer();
22+
}).AddJwtBearer(config =>
23+
{
24+
ConfigureJwtBearer(serviceCollection, config);
25+
});
2326
}
2427

2528
private static void ConfigureJwtBearer(IServiceCollection services, JwtBearerOptions config)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Security.Claims;
2+
using Microsoft.AspNetCore.Mvc;
3+
4+
namespace Micro.AppRegistration.Api.UserDataExtensions
5+
{
6+
public static class UserIdExtension
7+
{
8+
public static string? GetUserId(this ControllerBase controller)
9+
{
10+
return controller.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
11+
}
12+
}
13+
}

Micro.AppRegistration.Api/appsettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"DatabaseConfig": {
1414
"Host": "localhost",
15-
"Port": 15433,
15+
"Port": 15432,
1616
"Name": "app_registration",
1717
"User": "postgres",
1818
"Password": "postgres"

0 commit comments

Comments
 (0)