merge: integrate pos-transactions-bff auth and web updates
This commit is contained in:
commit
a4e5f0252d
@ -23,6 +23,8 @@ docker run --rm -p 8080:8080 --name pos-transactions-bff agilewebs/pos-transacti
|
||||
## Runtime Notes
|
||||
|
||||
- Exposes REST edge endpoints for transaction summary and payment capture.
|
||||
- Requires `ThalosAuth__BaseAddress` to resolve Thalos session introspection endpoint.
|
||||
- Returns standardized auth failures (`401|403|503`) with `x-correlation-id` propagation.
|
||||
|
||||
## Health Endpoint Consistency
|
||||
|
||||
|
||||
@ -38,8 +38,13 @@ Standard auth error payload:
|
||||
|
||||
- `401`: missing or invalid session
|
||||
- `403`: permission denied by identity service
|
||||
- `503`: identity service unavailable or timeout (`identity_unavailable|identity_timeout`)
|
||||
|
||||
## Correlation
|
||||
|
||||
- Incoming/outgoing correlation header: `x-correlation-id`
|
||||
- Correlation ID is forwarded to Thalos session validation call.
|
||||
|
||||
## Validation Rule
|
||||
|
||||
- Successful session introspection must also include `isAuthenticated=true` in Thalos response payload.
|
||||
|
||||
@ -3,6 +3,7 @@ using Microsoft.Extensions.Primitives;
|
||||
using Pos.Transactions.Bff.Application.Adapters;
|
||||
using Pos.Transactions.Bff.Application.Handlers;
|
||||
using Pos.Transactions.Bff.Contracts.Requests;
|
||||
using Pos.Transactions.Bff.Rest.Security;
|
||||
|
||||
const string CorrelationHeaderName = "x-correlation-id";
|
||||
const string SessionAccessCookieName = "thalos_session";
|
||||
@ -109,8 +110,30 @@ async Task<IResult?> EnforceSessionAsync(
|
||||
request.Headers.TryAddWithoutValidation("Cookie", cookieHeader);
|
||||
}
|
||||
|
||||
using var response = await httpClientFactory.CreateClient("ThalosAuth").SendAsync(request, ct);
|
||||
HttpResponseMessage response;
|
||||
try
|
||||
{
|
||||
response = await httpClientFactory.CreateClient("ThalosAuth").SendAsync(request, ct);
|
||||
}
|
||||
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.Forbidden)
|
||||
{
|
||||
return ErrorResponse(StatusCodes.Status403Forbidden, "forbidden", "Permission denied.", correlationId);
|
||||
@ -126,6 +149,13 @@ async Task<IResult?> EnforceSessionAsync(
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Pos.Transactions.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