-
@code {
- [Parameter] public bool IsAuthenticated { get; set; } = false;
+ [CascadingParameter]
+ private Task
? AuthStateTask { get; set; }
+
+ private System.Security.Claims.ClaimsPrincipal? UserPrincipal;
+
+ private string? Name { get; set; }
+ private string? Email { get; set; }
+ private DateTime? LoginTime { get; set; }
+
+ protected override async Task OnInitializedAsync()
+ {
+ if (AuthStateTask != null)
+ {
+ var authState = await AuthStateTask;
+
+ UserPrincipal = authState.User;
+
+ Name = UserPrincipal?.Identity?.Name;
+ Email = UserPrincipal?.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value;
+
+ var authTimeClaim = UserPrincipal?.FindFirst("auth_time")?.Value;
+
+ if (!string.IsNullOrEmpty(authTimeClaim) && long.TryParse(authTimeClaim, out long unixSeconds))
+ {
+ var dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(unixSeconds);
+ LoginTime = dateTimeOffset.LocalDateTime;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/ShopAdmin/Program.cs b/ShopAdmin/Program.cs
index a145f05..34ce093 100644
--- a/ShopAdmin/Program.cs
+++ b/ShopAdmin/Program.cs
@@ -65,6 +65,21 @@ builder.Services.AddAuthentication(options =>
NameClaimType = "name",
RoleClaimType = "groups"
};
+
+ options.Events = new OpenIdConnectEvents
+ {
+ OnRedirectToIdentityProviderForSignOut = async callbackContext =>
+ {
+ var request = callbackContext.Request;
+ string currentBaseUrl = $"{request.Scheme}://{request.Host}{request.PathBase}/";
+
+ callbackContext.ProtocolMessage.PostLogoutRedirectUri = currentBaseUrl;
+
+ var idToken = await callbackContext.HttpContext.GetTokenAsync("id_token");
+
+ if (!string.IsNullOrEmpty(idToken)) callbackContext.ProtocolMessage.IdTokenHint = idToken;
+ }
+ };
});
var app = builder.Build();
@@ -97,8 +112,18 @@ app.UseAuthorization();
app.MapStaticAssets();
app.MapGet("/auth/login", (string redirectUri = "/") =>
- Results.Challenge(new AuthenticationProperties { RedirectUri = redirectUri },[OpenIdConnectDefaults.AuthenticationScheme]));
-app.MapGet("/auth/logout", () => Results.SignOut(new AuthenticationProperties { RedirectUri = "/" }, [CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme]));
+ Results.Challenge(new AuthenticationProperties { RedirectUri = redirectUri }, [OpenIdConnectDefaults.AuthenticationScheme]));
+app.MapGet("/auth/logout", async (HttpContext context) =>
+{
+ await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
+
+ string currentBaseUrl = $"{context.Request.Scheme}://{context.Request.Host}{context.Request.PathBase}/";
+
+ await context.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
+ {
+ RedirectUri = currentBaseUrl
+ });
+});
app.MapRazorComponents()
.AddInteractiveServerRenderMode();
diff --git a/ShopAdmin/wwwroot/app.css b/ShopAdmin/wwwroot/app.css
index 5944cd6..c7838b2 100644
--- a/ShopAdmin/wwwroot/app.css
+++ b/ShopAdmin/wwwroot/app.css
@@ -42,7 +42,7 @@ html, body {
display: flex;
align-items: center;
justify-content: space-between;
- padding: 0 4rem 0 1rem;
+ padding: 0 1.5rem; /* Balanced horizontal spacing for both sides */
z-index: 1000;
border-bottom: 1px solid rgba(144, 224, 239, 0.15);
}
@@ -119,7 +119,7 @@ main {
/* --- Responsive Logic --- */
@media (max-width: 1200px) {
.top-bar {
- padding: 0 2rem;
+ padding: 0 1rem;
}
}
diff --git a/litecharms-shopadmin-uat.yml b/litecharms-shopadmin-uat.yml
index e1392cc..7586be7 100644
--- a/litecharms-shopadmin-uat.yml
+++ b/litecharms-shopadmin-uat.yml
@@ -14,6 +14,7 @@ data:
ASPNETCORE_URLS: "http://0.0.0.0:8080"
Monitoring__Address: "http://aspire-dashboard-service.aspire.svc.cluster.local:18889"
Monitoring__ServiceName: "LiteCharms.ShopAdmin.Uat"
+ IdKongisa__Authority: "https://id.khongisa.co.za/application/o/litecharms-shopadmin"
---
apiVersion: v1
kind: Secret
@@ -25,6 +26,8 @@ data:
connection-string: SG9zdD0xOTIuMTY4LjEuMTcwO0RhdGFiYXNlPXNob3AtZGV2O1VzZXJuYW1lPXNob3AtZGV2LXVzZXI7UGFzc3dvcmQ9a1ZWbW9XS0ozeHpnUVg7UGVyc2lzdCBTZWN1cml0eSBJbmZvPVRydWU=
connection-string-quartz: SG9zdD0xOTIuMTY4LjEuMTcwO0RhdGFiYXNlPXNjaGVkdWxlci1kZXY7VXNlcm5hbWU9c2NoZWR1bGVyLWRldi11c2VyO1Bhc3N3b3JkPWtWVm1vV0tKM3h6Z1FYO1BlcnNpc3QgU2VjdXJpdHkgSW5mbz1UcnVl
aspire-apikey: bWMzRzYzSzJqNVpPRXNpMEFqTW9qTFRYbTFLRVpGY3R6SUlqU3dEaVRHdXQ4cUdTa1B1V3d4R1AxUmJzY0pVbw==
+ auth-clientid: NUxldE5hSERsUlhOWXo1N3FkMVV1RWN4R01uUDNmT3FXc0RHcWdjUg==
+ auth-clientsecret: a3ZxN3k1anc0M0g4WDRjQW91eGRqRDhNNXdxVUhUQ2I4UjNSVjNVWjI4TUZjTk51NWxhM3g3V1ZZRzQ2QnJFMjVPMnhXRmhoeEk0VXNSaFlMTHRqSGRhWWVrUTBmdHpIQ3ZNczV5TXdRdERpcDBkM3QzTkNDa0RtN1JXeW1XSTg=
---
apiVersion: v1
kind: PersistentVolumeClaim
@@ -102,6 +105,16 @@ spec:
secretKeyRef:
name: shopadmin-secrets
key: aspire-apikey
+ - name: IdKongisa__ClientId
+ valueFrom:
+ secretKeyRef:
+ name: shopadmin-secrets
+ key: auth-clientid
+ - name: IdKongisa__ClientSecret
+ valueFrom:
+ secretKeyRef:
+ name: shopadmin-secrets
+ key: auth-clientsecret
volumeMounts:
- name: data
mountPath: /app/wwwroot/content