Compare commits
No commits in common. "36c7c8c6bab664773814eb20f1cd6b61fdaadecd" and "42a6934f7f76646d214266b303378d0948d73b7a" have entirely different histories.
36c7c8c6ba
...
42a6934f7f
@ -23,8 +23,6 @@ docker run --rm -p 8080:8080 --name kitchen-ops-bff agilewebs/kitchen-ops-bff:de
|
|||||||
## Runtime Notes
|
## Runtime Notes
|
||||||
|
|
||||||
- Exposes REST edge endpoints for kitchen operations dashboards.
|
- Exposes REST edge endpoints for kitchen operations dashboards.
|
||||||
- Requires `ThalosAuth__BaseAddress` to resolve Thalos session introspection endpoint.
|
|
||||||
- Returns standardized auth failures (`401|403|503`) with `x-correlation-id` propagation.
|
|
||||||
|
|
||||||
## Health Endpoint Consistency
|
## Health Endpoint Consistency
|
||||||
|
|
||||||
|
|||||||
@ -38,13 +38,8 @@ Standard auth error payload:
|
|||||||
|
|
||||||
- `401`: missing or invalid session
|
- `401`: missing or invalid session
|
||||||
- `403`: permission denied by identity service
|
- `403`: permission denied by identity service
|
||||||
- `503`: identity service unavailable or timeout (`identity_unavailable|identity_timeout`)
|
|
||||||
|
|
||||||
## Correlation
|
## Correlation
|
||||||
|
|
||||||
- Incoming/outgoing correlation header: `x-correlation-id`
|
- Incoming/outgoing correlation header: `x-correlation-id`
|
||||||
- Correlation ID is forwarded to Thalos session validation call.
|
- Correlation ID is forwarded to Thalos session validation call.
|
||||||
|
|
||||||
## Validation Rule
|
|
||||||
|
|
||||||
- Successful session introspection must also include `isAuthenticated=true` in Thalos response payload.
|
|
||||||
|
|||||||
@ -3,7 +3,6 @@ using Kitchen.Ops.Bff.Application.Adapters;
|
|||||||
using Kitchen.Ops.Bff.Application.Handlers;
|
using Kitchen.Ops.Bff.Application.Handlers;
|
||||||
using Kitchen.Ops.Bff.Contracts.Requests;
|
using Kitchen.Ops.Bff.Contracts.Requests;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Kitchen.Ops.Bff.Rest.Security;
|
|
||||||
|
|
||||||
const string CorrelationHeaderName = "x-correlation-id";
|
const string CorrelationHeaderName = "x-correlation-id";
|
||||||
const string SessionAccessCookieName = "thalos_session";
|
const string SessionAccessCookieName = "thalos_session";
|
||||||
@ -110,50 +109,21 @@ async Task<IResult?> EnforceSessionAsync(
|
|||||||
request.Headers.TryAddWithoutValidation("Cookie", cookieHeader);
|
request.Headers.TryAddWithoutValidation("Cookie", cookieHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpResponseMessage response;
|
using var response = await httpClientFactory.CreateClient("ThalosAuth").SendAsync(request, ct);
|
||||||
try
|
|
||||||
|
if (response.StatusCode == HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
response = await httpClientFactory.CreateClient("ThalosAuth").SendAsync(request, ct);
|
return ErrorResponse(StatusCodes.Status403Forbidden, "forbidden", "Permission denied.", correlationId);
|
||||||
}
|
|
||||||
catch (HttpRequestException)
|
|
||||||
{
|
|
||||||
return ErrorResponse(
|
|
||||||
StatusCodes.Status503ServiceUnavailable,
|
|
||||||
"identity_unavailable",
|
|
||||||
"Identity service is temporarily unavailable.",
|
|
||||||
correlationId);
|
|
||||||
}
|
|
||||||
catch (TaskCanceledException)
|
|
||||||
{
|
|
||||||
return ErrorResponse(
|
|
||||||
StatusCodes.Status503ServiceUnavailable,
|
|
||||||
"identity_timeout",
|
|
||||||
"Identity service did not respond in time.",
|
|
||||||
correlationId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using (response)
|
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||||
{
|
{
|
||||||
if (response.StatusCode == HttpStatusCode.Forbidden)
|
return ErrorResponse(StatusCodes.Status401Unauthorized, "unauthorized", "Unauthorized request.", correlationId);
|
||||||
{
|
}
|
||||||
return ErrorResponse(StatusCodes.Status403Forbidden, "forbidden", "Permission denied.", correlationId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
return ErrorResponse(StatusCodes.Status401Unauthorized, "unauthorized", "Unauthorized request.", correlationId);
|
return ErrorResponse(StatusCodes.Status401Unauthorized, "session_invalid", "Session validation failed.", correlationId);
|
||||||
}
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
return ErrorResponse(StatusCodes.Status401Unauthorized, "session_invalid", "Session validation failed.", correlationId);
|
|
||||||
}
|
|
||||||
|
|
||||||
var payload = await response.Content.ReadAsStringAsync(ct);
|
|
||||||
if (!SessionMePayloadParser.IsAuthenticated(payload))
|
|
||||||
{
|
|
||||||
return ErrorResponse(StatusCodes.Status401Unauthorized, "session_invalid", "Session validation failed.", correlationId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace Kitchen.Ops.Bff.Rest.Security;
|
|
||||||
|
|
||||||
public static class SessionMePayloadParser
|
|
||||||
{
|
|
||||||
public static bool IsAuthenticated(string payload)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(payload))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var document = JsonDocument.Parse(payload);
|
|
||||||
if (!document.RootElement.TryGetProperty("isAuthenticated", out var value))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value.ValueKind == JsonValueKind.True;
|
|
||||||
}
|
|
||||||
catch (JsonException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user