Initial commit with inital CMS
This commit is contained in:
+35
@@ -0,0 +1,35 @@
|
||||
# Auth Service Design — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document beschrijft de `IAuthService` die verantwoordelijk is voor token-management.
|
||||
|
||||
## 1. Interface definitie
|
||||
|
||||
```csharp
|
||||
public interface IAuthService
|
||||
{
|
||||
Task<TokenResponse> AuthenticateAsync(string email, string password);
|
||||
Task<TokenResponse> RefreshTokenAsync(string accessToken, string refreshToken);
|
||||
Task RevokeTokenAsync(string refreshToken);
|
||||
}
|
||||
```
|
||||
|
||||
## 2. JWT Configuratie
|
||||
|
||||
- **Signing Key**: Wordt uit de environment variable `JWT_SIGNING_KEY` gelezen.
|
||||
- **Issuer/Audience**: Worden geconfigureerd in `appsettings.json`.
|
||||
- **Claims**:
|
||||
- `sub`: UserId.
|
||||
- `email`: Gebruikers e-mail.
|
||||
- `role`: Gebruikers rol (bijv. "Administrator").
|
||||
- `exp`: Expiration time.
|
||||
|
||||
## 3. Refresh Token Rotation Logic
|
||||
|
||||
Bij een refresh request:
|
||||
1. Valideer de `refreshToken` string tegen de database.
|
||||
2. Controleer op Re-use: Indien de `IsUsed` vlag al op `true` staat, trek dan **alle** tokens van die gebruiker in (NFR-ID-SEC-03).
|
||||
3. Indien geldig:
|
||||
- Markeer huidig token als `IsUsed = true`.
|
||||
- Genereer een nieuw cryptografisch veilig geheim (32 bytes Base64).
|
||||
- Sla het nieuwe token op met een nieuwe `ExpiryDate`.
|
||||
- Retourneer het nieuwe `AccessToken` en `RefreshToken`.
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
# Authorization Design — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document beschrijft de technische implementatie van de hiërarchische autorisatie.
|
||||
|
||||
## 1. HierarchicalRoleRequirement
|
||||
|
||||
We maken gebruik van een custom requirement om rollen te vergelijken.
|
||||
|
||||
```csharp
|
||||
public class HierarchicalRoleRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public HierarchicalRoleRequirement(string minimumRequiredRole)
|
||||
{
|
||||
MinimumRequiredRole = minimumRequiredRole;
|
||||
}
|
||||
|
||||
public string MinimumRequiredRole { get; }
|
||||
}
|
||||
```
|
||||
|
||||
## 2. HierarchicalRoleHandler
|
||||
|
||||
De handler valideert of de rollen-hiërarchie wordt gerespecteerd.
|
||||
|
||||
- **Logic**:
|
||||
1. Haal de rol-claim op van de huidige gebruiker.
|
||||
2. Haal de doel-gebruiker op uit de route of body.
|
||||
3. Vergelijk de numerieke waarden van beide rollen.
|
||||
4. Slaag alleen als de huidige gebruiker een hogere of gelijke rol heeft (afhankelijk van de actie).
|
||||
|
||||
## 3. Setup Endpoint Protection
|
||||
|
||||
Het `SetupController.Init` endpoint controleert direct in de database of er al een Owner bestaat:
|
||||
|
||||
```csharp
|
||||
[HttpPost("init")]
|
||||
public async Task<IActionResult> Init(SetupRequest request)
|
||||
{
|
||||
var anyOwner = await _userManager.GetUsersInRoleAsync("Owner");
|
||||
if (anyOwner.Any())
|
||||
{
|
||||
return Forbidden("Systeem is reeds geïnitialiseerd.");
|
||||
}
|
||||
// Verwerk creatie...
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Module-specifieke Policies
|
||||
|
||||
Er worden dynamische policies aangemaakt voor module-permissies:
|
||||
- Patroon: `Module:{ModuleName}:{Permission}` (bijv. `Module:Blog:Delete`).
|
||||
- De handler controleert de `ModulePermissions` tabel voor de huidige gebruiker.
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
# Database Design — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document beschrijft de database schema configuratie voor de identiteitsmodule.
|
||||
|
||||
## 1. DbContext Mapping (Identity)
|
||||
|
||||
De `ApplicationDbContext` erft over van `IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>`.
|
||||
In `OnModelCreating` worden de tabelnamen geconfigureerd:
|
||||
|
||||
```csharp
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
|
||||
builder.Entity<ApplicationUser>(entity => { entity.ToTable("Users"); });
|
||||
builder.Entity<IdentityRole<Guid>>(entity => { entity.ToTable("Roles"); });
|
||||
builder.Entity<IdentityUserRole<Guid>>(entity => { entity.ToTable("UserRoles"); });
|
||||
builder.Entity<IdentityUserClaim<Guid>>(entity => { entity.ToTable("UserClaims"); });
|
||||
builder.Entity<IdentityUserLogin<Guid>>(entity => { entity.ToTable("UserLogins"); });
|
||||
builder.Entity<IdentityRoleClaim<Guid>>(entity => { entity.ToTable("RoleClaims"); });
|
||||
builder.Entity<IdentityUserToken<Guid>>(entity => { entity.ToTable("UserTokens"); });
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Aanvullende Tabellen
|
||||
|
||||
### RefreshTokens
|
||||
- **Tabel**: `RefreshTokens`
|
||||
- **PK**: `Id` (Guid)
|
||||
- **FK**: `UserId` -> `Users.Id`
|
||||
- **Index**: `Token` (Unique)
|
||||
|
||||
### Invitations
|
||||
- **Tabel**: `Invitations`
|
||||
- **PK**: `Id` (Guid)
|
||||
- **Index**: `Token` (Unique)
|
||||
- **Email**: `NVARCHAR(256)`
|
||||
|
||||
### ModulePermissions
|
||||
- **Tabel**: `ModulePermissions`
|
||||
- **Composite PK**: `(UserId, ModuleName, Permission)`
|
||||
- **FK**: `UserId` -> `Users.Id`
|
||||
|
||||
## 3. Auditing (NFR-ID-SEC-03)
|
||||
|
||||
Er wordt een aparte `AuditLogs` tabel aangemaakt voor het loggen van mutaties:
|
||||
- `Id` (Guid)
|
||||
- `Timestamp` (DateTimeOffset)
|
||||
- `ActorId` (Guid - De uitvoerder)
|
||||
- `Action` (String - bijv. "RoleChange", "UserCreated")
|
||||
- `EntityId` (Guid - Het doelobject)
|
||||
- `Details` (JSON/String - Oude vs Nieuwe waarden)
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
# Invitation Design — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document beschrijft de technische implementatie van het uitnodigingssysteem.
|
||||
|
||||
## 1. IInvitationService
|
||||
|
||||
```csharp
|
||||
public interface IInvitationService
|
||||
{
|
||||
Task<string> CreateInvitationAsync(string email, string role);
|
||||
Task<bool> ValidateInvitationAsync(string token);
|
||||
Task CompleteInvitationAsync(string token, string password);
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Token Generatie
|
||||
|
||||
Het `InvitationToken` wordt gegenereerd met de `RandomNumberGenerator`:
|
||||
|
||||
```csharp
|
||||
public string GenerateSecureToken()
|
||||
{
|
||||
var bytes = new byte[32];
|
||||
RandomNumberGenerator.Fill(bytes);
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Workflow Details
|
||||
|
||||
1. **Creatie**:
|
||||
- Een `Invitation` record wordt aangemaakt in de database.
|
||||
- Het `Token` wordt gehasht opgeslagen (net als een wachtwoord) om misbruik bij database-lekken te voorkomen.
|
||||
2. **Validatie**:
|
||||
- Het systeem zoekt het record op basis van de token-string.
|
||||
- Controleert `ExpiryDate` en `IsAccepted`.
|
||||
3. **Afronding**:
|
||||
- Bij `CompleteInvitationAsync` wordt de `ApplicationUser` aangemaakt via de `UserManager`.
|
||||
- De rol wordt toegekend.
|
||||
- Het uitnodigingsrecord wordt gemarkeerd als `IsAccepted = true`.
|
||||
Reference in New Issue
Block a user