ปรับการแกะ keycloakid มาจาก token เนื่องจาก middleware ทำงานก่อน auth middleware จึงทำให้ยังไม่มี context.User เลยเอาไปหา keycloakId ไมได้
Some checks failed
release-dev / release-dev (push) Failing after 13s

This commit is contained in:
Suphonchai Phoonsawat 2025-06-24 12:49:24 +07:00
parent 89a90099a7
commit 8f9b40c303

View file

@ -22,7 +22,6 @@ namespace BMA.EHR.Domain.Middlewares
private string Uri = "";
private string IndexFormat = "";
private string SystemName = "";
private string APIKey = "";
public CombinedErrorHandlerAndLoggingMiddleware(RequestDelegate next, IConfiguration configuration)
{
@ -50,7 +49,7 @@ namespace BMA.EHR.Domain.Middlewares
// อ่าน Request Body
string requestBody = await ReadRequestBodyAsync(context);
if (requestBody != "")
if (!string.IsNullOrEmpty(requestBody))
{
requestBodyJson = await FormatRequestBody(context, requestBody);
}
@ -62,13 +61,26 @@ namespace BMA.EHR.Domain.Middlewares
// เปลี่ยน stream ของ Response เพื่อให้สามารถอ่านได้
context.Response.Body = memoryStream;
var keycloakId = context.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? Guid.Empty.ToString("D");
string keycloakId = Guid.Empty.ToString("D");
var token = context.Request.Headers["Authorization"];
GetProfileByKeycloakIdLocal? pf = null;
// ลองดึง keycloakId จาก JWT token ก่อน (ถ้ามี)
try
{
pf = await GetProfileByKeycloakIdAsync(Guid.Parse(keycloakId), token);
keycloakId = await ExtractKeycloakIdFromToken(token);
}
catch (Exception ex)
{
Console.WriteLine($"Error extracting keycloakId from token: {ex.Message}");
}
try
{
if (Guid.TryParse(keycloakId, out var parsedId) && parsedId != Guid.Empty)
{
pf = await GetProfileByKeycloakIdAsync(parsedId, token);
}
}
catch (Exception ex)
{
@ -80,8 +92,32 @@ namespace BMA.EHR.Domain.Middlewares
await _next(context);
Console.WriteLine($"Request completed with status: {context.Response.StatusCode}");
// หลังจาก Authentication middleware ทำงานแล้ว ลองดึง claims อีกครั้ง
if (context.User?.Identity?.IsAuthenticated == true)
{
var authenticatedKeycloakId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value
?? context.User.FindFirst("sub")?.Value;
if (!string.IsNullOrEmpty(authenticatedKeycloakId) && authenticatedKeycloakId != keycloakId)
{
keycloakId = authenticatedKeycloakId;
Console.WriteLine($"Updated keycloakId from authenticated user: {keycloakId}");
// อัพเดต profile ด้วย keycloakId ที่ถูกต้อง
try
{
if (Guid.TryParse(keycloakId, out var parsedId))
{
pf = await GetProfileByKeycloakIdAsync(parsedId, token);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error updating profile after authentication: {ex.Message}");
}
}
}
// จัดการ response format หลังจาก request ผ่าน pipeline แล้ว
// รวมถึงการจัดการ 401/403 ที่มาจาก Authentication middleware
await FormatResponse(context, memoryStream);
}
catch (ObjectDisposedException)
@ -324,10 +360,10 @@ namespace BMA.EHR.Domain.Middlewares
memoryStream.Seek(0, SeekOrigin.Begin);
var responseBody = new StreamReader(memoryStream).ReadToEnd();
if (responseBody != "")
if (!string.IsNullOrEmpty(responseBody))
{
var contentType = context.Response.ContentType;
var isFileResponse = !contentType.StartsWith("application/json") && (
var isFileResponse = !contentType.StartsWith("application/json") && !contentType.StartsWith("text/html") && (
contentType.StartsWith("application/") ||
contentType.StartsWith("image/") ||
contentType.StartsWith("audio/") ||
@ -401,7 +437,7 @@ namespace BMA.EHR.Domain.Middlewares
exception = caughtException?.ToString()
};
client.IndexDocument(logData);
await client.IndexDocumentAsync(logData);
}
catch (Exception ex)
{
@ -453,6 +489,67 @@ namespace BMA.EHR.Domain.Middlewares
return msg;
}
private async Task<string> ExtractKeycloakIdFromToken(string? authorizationHeader)
{
try
{
if (string.IsNullOrEmpty(authorizationHeader) || !authorizationHeader.StartsWith("Bearer "))
{
return Guid.Empty.ToString("D");
}
var token = authorizationHeader.Replace("Bearer ", "");
// แยก JWT token เพื่อดึง payload (แบบง่าย โดยไม่ verify signature)
var parts = token.Split('.');
if (parts.Length != 3)
{
return Guid.Empty.ToString("D");
}
// Decode Base64 payload
var payload = parts[1];
// เพิ่ม padding ถ้าจำเป็น
var padLength = 4 - (payload.Length % 4);
if (padLength != 4)
{
payload += new string('=', padLength);
}
var payloadBytes = Convert.FromBase64String(payload);
var payloadJson = System.Text.Encoding.UTF8.GetString(payloadBytes);
Console.WriteLine($"JWT Payload: {payloadJson}");
// Parse JSON และดึง sub (subject) claim
var jsonDoc = JsonDocument.Parse(payloadJson);
// ลองหา keycloak ID ใน claims ต่างๆ
string? keycloakId = null;
if (jsonDoc.RootElement.TryGetProperty("sub", out var subElement))
{
keycloakId = subElement.GetString();
}
else if (jsonDoc.RootElement.TryGetProperty("nameid", out var nameidElement))
{
keycloakId = nameidElement.GetString();
}
else if (jsonDoc.RootElement.TryGetProperty("user_id", out var userIdElement))
{
keycloakId = userIdElement.GetString();
}
return keycloakId ?? Guid.Empty.ToString("D");
}
catch (Exception ex)
{
Console.WriteLine($"Error extracting keycloak ID from token: {ex.Message}");
return Guid.Empty.ToString("D");
}
}
protected async Task<string> GetExternalAPIAsync(string apiPath, string accessToken, string apiKey)
{
try
@ -509,7 +606,7 @@ namespace BMA.EHR.Domain.Middlewares
}
}
// Model classes (ถ้ายังไม่มีใน namespace นี้)
// Model classes
public class GetProfileByKeycloakIdLocal
{
public Guid Id { get; set; }
@ -546,5 +643,4 @@ namespace BMA.EHR.Domain.Middlewares
public GetProfileByKeycloakIdLocal? Result { get; set; }
}
}