ปรับการแกะ keycloakid มาจาก token เนื่องจาก middleware ทำงานก่อน auth middleware จึงทำให้ยังไม่มี context.User เลยเอาไปหา keycloakId ไมได้
Some checks failed
release-dev / release-dev (push) Failing after 13s
Some checks failed
release-dev / release-dev (push) Failing after 13s
This commit is contained in:
parent
89a90099a7
commit
8f9b40c303
1 changed files with 106 additions and 10 deletions
|
|
@ -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; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue