From a8ed99f134e9076ba6334024beaea831d4b5371d Mon Sep 17 00:00:00 2001
From: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com>
Date: Thu, 30 Apr 2026 15:56:03 +0000
Subject: [PATCH] chore: update
---
eatery-service/pom.xml | 27 ++---
.../provider/ManualSecurityFilter.java | 32 ++++++
gateway-service/pom.xml | 26 ++---
.../drinkool/controller/EateryController.java | 60 +++++++----
.../drinkool/filters/HeaderRolesFilter.java | 99 +++++++++++++++++++
.../filters/InternalHeaderGatewayFilter.java | 58 -----------
.../src/main/resources/application.properties | 8 +-
k8s/base/gateway.yaml | 4 -
lib/pom.xml | 15 +--
.../lib/utils/BaseHeaderAuthentication.java | 43 ++++++++
.../lib/utils/HeaderIdentityProvider.java | 38 -------
11 files changed, 257 insertions(+), 153 deletions(-)
create mode 100644 eatery-service/src/main/java/com/drinkool/provider/ManualSecurityFilter.java
create mode 100644 gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java
create mode 100644 lib/src/main/java/com/drinkool/lib/utils/BaseHeaderAuthentication.java
delete mode 100644 lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java
diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml
index dd704c2..1178c1c 100644
--- a/eatery-service/pom.xml
+++ b/eatery-service/pom.xml
@@ -1,8 +1,8 @@
-
+
4.0.0
@@ -20,11 +20,9 @@
3.15.0
25
UTF-8
- UTF-8
+ UTF-8
quarkus-bom
- io.quarkus.platform
+ io.quarkus.platform
3.32.4
true
3.5.4
@@ -48,6 +46,11 @@
lib
${project.version}
+
+ io.quarkus
+ quarkus-security
+ provided
+
net.datafaker
datafaker
@@ -138,8 +141,7 @@
@{argLine}
- org.jboss.logmanager.LogManager
+ org.jboss.logmanager.LogManager
${maven.home}
1
@@ -163,8 +165,7 @@
${project.build.directory}/${project.build.finalName}-runner
- org.jboss.logmanager.LogManager
+ org.jboss.logmanager.LogManager
${maven.home}
@@ -187,4 +188,4 @@
-
+
\ No newline at end of file
diff --git a/eatery-service/src/main/java/com/drinkool/provider/ManualSecurityFilter.java b/eatery-service/src/main/java/com/drinkool/provider/ManualSecurityFilter.java
new file mode 100644
index 0000000..5a98c4b
--- /dev/null
+++ b/eatery-service/src/main/java/com/drinkool/provider/ManualSecurityFilter.java
@@ -0,0 +1,32 @@
+package com.drinkool.provider;
+
+import io.quarkus.security.identity.IdentityProviderManager;
+import io.quarkus.security.identity.SecurityIdentity;
+import io.quarkus.vertx.http.runtime.security.ChallengeData;
+import io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism;
+import io.smallrye.mutiny.Uni;
+import io.vertx.ext.web.RoutingContext;
+import jakarta.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class ManualSecurityFilter implements HttpAuthenticationMechanism {
+
+ @Override
+ public Uni authenticate(
+ RoutingContext context,
+ IdentityProviderManager identityProviderManager
+ ) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException(
+ "Unimplemented method 'authenticate'"
+ );
+ }
+
+ @Override
+ public Uni getChallenge(RoutingContext context) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException(
+ "Unimplemented method 'getChallenge'"
+ );
+ }
+}
diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml
index 72c5c83..4b49027 100644
--- a/gateway-service/pom.xml
+++ b/gateway-service/pom.xml
@@ -1,8 +1,8 @@
-
+
4.0.0
@@ -20,11 +20,9 @@
3.15.0
25
UTF-8
- UTF-8
+ UTF-8
quarkus-bom
- io.quarkus.platform
+ io.quarkus.platform
3.32.4
true
3.5.4
@@ -48,6 +46,10 @@
jose4j
0.9.6
+
+ io.quarkus
+ quarkus-security
+
io.quarkus
quarkus-smallrye-graphql-client
@@ -110,8 +112,7 @@
@{argLine}
- org.jboss.logmanager.LogManager
+ org.jboss.logmanager.LogManager
${maven.home}
1
@@ -135,8 +136,7 @@
${project.build.directory}/${project.build.finalName}-runner
- org.jboss.logmanager.LogManager
+ org.jboss.logmanager.LogManager
${maven.home}
@@ -158,4 +158,4 @@
-
+
\ No newline at end of file
diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java
index b7de506..42830e7 100644
--- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java
+++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java
@@ -1,39 +1,59 @@
package com.drinkool.controller;
+import com.drinkool.InternalValue;
import com.drinkool.dtos.GraphqlDto;
-import io.smallrye.graphql.client.GraphQLClient;
-import io.smallrye.graphql.client.GraphQLError;
import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient;
+import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.stream.Collectors;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
@Path("/api/eatery")
public class EateryController {
- @GraphQLClient("eatery")
- DynamicGraphQLClient dynamicClient;
+ @ConfigProperty(name = "quarkus.smallrye-graphql-client.eatery.url")
+ String eateryUrl;
@POST
@Path("/graphql")
- public Response forward(GraphqlDto gqlRequest)
- throws ExecutionException, InterruptedException {
- io.smallrye.graphql.client.Response response = dynamicClient.executeSync(
- gqlRequest.query,
- gqlRequest.variables
- );
+ public Response forward(
+ GraphqlDto gqlRequest,
+ @Context HttpHeaders httpHeaders
+ ) {
+ DynamicGraphQLClientBuilder builder =
+ DynamicGraphQLClientBuilder.newBuilder().url(eateryUrl);
- if (response.hasError()) {
- return Response.status(400)
- .entity(response.getErrors().toString())
+ httpHeaders
+ .getRequestHeaders()
+ .forEach((name, values) -> {
+ String headerName = name.toLowerCase();
+
+ if (headerName.startsWith(InternalValue.headerId.toLowerCase())) {
+ if (!values.isEmpty()) {
+ builder.header(name, values.get(0));
+ }
+ }
+ });
+
+ try (DynamicGraphQLClient tempClient = builder.build()) {
+ io.smallrye.graphql.client.Response response = tempClient.executeSync(
+ gqlRequest.query,
+ gqlRequest.variables
+ );
+
+ if (response.hasError()) {
+ return Response.status(400).entity(response.getErrors()).build();
+ }
+
+ return Response.ok(response.getData()).build();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return Response.serverError()
+ .entity("Lỗi kết nối tới service Eatery")
.build();
}
-
- return jakarta.ws.rs.core.Response.ok(
- response.getData().toString()
- ).build();
}
}
diff --git a/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java b/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java
new file mode 100644
index 0000000..69a5b1d
--- /dev/null
+++ b/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java
@@ -0,0 +1,99 @@
+package com.drinkool.filters;
+
+import com.drinkool.InternalValue;
+import com.drinkool.lib.utils.BaseHeaderAuthentication;
+import io.quarkus.security.identity.IdentityProviderManager;
+import io.quarkus.security.identity.SecurityIdentity;
+import io.quarkus.security.runtime.QuarkusSecurityIdentity;
+import io.smallrye.mutiny.Uni;
+import io.vertx.core.MultiMap;
+import io.vertx.ext.web.RoutingContext;
+import jakarta.enterprise.context.ApplicationScoped;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import org.jose4j.jwt.JwtClaims;
+import org.jose4j.jwt.consumer.JwtConsumer;
+import org.jose4j.jwt.consumer.JwtConsumerBuilder;
+import org.jose4j.keys.HmacKey;
+
+@ApplicationScoped
+public class HeaderRolesFilter extends BaseHeaderAuthentication {
+
+ @ConfigProperty(name = "gateway.jwt.secret")
+ String SECRET_KEY;
+
+ private boolean isSystemClaim(String key) {
+ return List.of("iss", "sub", "aud", "exp", "nbf", "iat", "jti").contains(
+ key
+ );
+ }
+
+ private void removeForeignHeader(RoutingContext context) {
+ MultiMap headers = context.request().headers();
+ List keysToRemove = new ArrayList<>();
+
+ for (String key : headers.names()) {
+ if (key.toLowerCase().startsWith(InternalValue.headerId.toLowerCase())) {
+ keysToRemove.add(key);
+ }
+ }
+
+ for (String key : keysToRemove) {
+ headers.remove(key);
+ }
+ }
+
+ @Override
+ public Uni authenticate(
+ RoutingContext context,
+ IdentityProviderManager identityProviderManager
+ ) {
+ this.removeForeignHeader(context);
+
+ var cookie = context.request().getCookie(InternalValue.cookieName);
+
+ if (cookie == null) return Uni.createFrom().nullItem();
+
+ try {
+ JwtConsumer jwtConsumer = new JwtConsumerBuilder()
+ .setRequireExpirationTime()
+ .setVerificationKey(new HmacKey(SECRET_KEY.getBytes()))
+ .build();
+
+ JwtClaims claims = jwtConsumer.processToClaims(cookie.getValue());
+ Map allClaims = claims.getClaimsMap();
+
+ allClaims.forEach((key, value) -> {
+ if (!isSystemClaim(key) && value != null) {
+ context
+ .request()
+ .headers()
+ .add(InternalValue.headerId + key, value.toString());
+ }
+ });
+
+ String role = context.request().getHeader(InternalValue.role);
+ String userId = context.request().getHeader(InternalValue.userId);
+
+ System.out.println(
+ "HeaderRolesFilter - Authenticated: " +
+ role +
+ " - " +
+ context.request().headers().toString()
+ );
+
+ return Uni.createFrom().item(
+ QuarkusSecurityIdentity.builder()
+ .setPrincipal(() -> userId)
+ .addRole(role)
+ .build()
+ );
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+
+ return Uni.createFrom().nullItem();
+ }
+ }
+}
diff --git a/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java b/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java
index 99afa06..0872821 100644
--- a/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java
+++ b/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java
@@ -1,19 +1,15 @@
package com.drinkool.filters;
import com.drinkool.InternalValue;
-import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.*;
import jakarta.ws.rs.core.*;
import java.util.*;
import org.eclipse.microprofile.config.inject.ConfigProperty;
-import org.jboss.resteasy.reactive.server.ServerRequestFilter;
import org.jboss.resteasy.reactive.server.ServerResponseFilter;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
-import org.jose4j.jwt.consumer.JwtConsumer;
-import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.keys.HmacKey;
public class InternalHeaderGatewayFilter {
@@ -21,60 +17,6 @@ public class InternalHeaderGatewayFilter {
@ConfigProperty(name = "gateway.jwt.secret")
String SECRET_KEY;
- private boolean isSystemClaim(String key) {
- return List.of("iss", "sub", "aud", "exp", "nbf", "iat", "jti").contains(
- key
- );
- }
-
- @ServerRequestFilter(preMatching = true)
- public Uni handleRequestHeaders(
- ContainerRequestContext requestContext
- ) {
- requestContext
- .getHeaders()
- .keySet()
- .removeIf(
- key ->
- key.equalsIgnoreCase(InternalValue.headerId) ||
- key.toLowerCase().startsWith(InternalValue.headerId.toLowerCase())
- );
-
- Map cookies = requestContext.getCookies();
- Cookie authCookie = cookies.get(InternalValue.cookieName);
-
- if (authCookie == null) return Uni.createFrom().nullItem();
-
- return Uni.createFrom().item(() -> {
- try {
- String token = authCookie.getValue();
-
- JwtConsumer jwtConsumer = new JwtConsumerBuilder()
- .setRequireExpirationTime()
- .setVerificationKey(new HmacKey(SECRET_KEY.getBytes()))
- .build();
-
- JwtClaims claims = jwtConsumer.processToClaims(token);
-
- Map allClaims = claims.getClaimsMap();
-
- allClaims.forEach((key, value) -> {
- if (!isSystemClaim(key) && value != null) {
- String headerName = InternalValue.headerId + (key);
-
- requestContext.getHeaders().add(headerName, value.toString());
- }
- });
- } catch (Exception e) {
- return Response.status(Response.Status.UNAUTHORIZED)
- .entity("InvalidToken")
- .build();
- }
-
- return null;
- });
- }
-
@ServerResponseFilter(priority = Priorities.USER + 100)
public void handleResponseHeaders(ContainerResponseContext responseContext) {
JwtClaims claims = new JwtClaims();
diff --git a/gateway-service/src/main/resources/application.properties b/gateway-service/src/main/resources/application.properties
index be0c229..ec3257a 100644
--- a/gateway-service/src/main/resources/application.properties
+++ b/gateway-service/src/main/resources/application.properties
@@ -10,4 +10,10 @@ quarkus.container-image.additional-tags=latest
# Build
quarkus.native.container-build=true
quarkus.native.remote-container-build=true
-quarkus.native.additional-build-args=--future-defaults=all
\ No newline at end of file
+quarkus.native.additional-build-args=--future-defaults=all
+
+# Rest Client
+quarkus.rest-client.account.url=http://account-service
+
+# GraphQL Client
+quarkus.smallrye-graphql-client.eatery.url=http://eatery-service/graphql
\ No newline at end of file
diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml
index 5eaf5ad..c0fb9c8 100644
--- a/k8s/base/gateway.yaml
+++ b/k8s/base/gateway.yaml
@@ -19,10 +19,6 @@ spec:
ports:
- containerPort: 8080
env:
- - name: QUARKUS_REST_CLIENT_ACCOUNT_URL
- value: "http://account-service"
- - name: QUARKUS_SMALLRYE_GRAPHQL_CLIENT_EATERY_URL
- value: "http://eatery-service/graphql"
- name: GATEWAY_JWT_SECRET
valueFrom:
secretKeyRef:
diff --git a/lib/pom.xml b/lib/pom.xml
index e871486..ce92231 100644
--- a/lib/pom.xml
+++ b/lib/pom.xml
@@ -1,8 +1,8 @@
-
+
4.0.0
@@ -24,7 +24,10 @@
io.quarkus
quarkus-security
- provided
+
+
+ io.quarkus
+ quarkus-vertx-http
com.fasterxml.jackson.core
@@ -60,4 +63,4 @@
test
-
+
\ No newline at end of file
diff --git a/lib/src/main/java/com/drinkool/lib/utils/BaseHeaderAuthentication.java b/lib/src/main/java/com/drinkool/lib/utils/BaseHeaderAuthentication.java
new file mode 100644
index 0000000..25d3c41
--- /dev/null
+++ b/lib/src/main/java/com/drinkool/lib/utils/BaseHeaderAuthentication.java
@@ -0,0 +1,43 @@
+package com.drinkool.lib.utils;
+
+import com.drinkool.InternalValue;
+import io.quarkus.security.identity.IdentityProviderManager;
+import io.quarkus.security.identity.SecurityIdentity;
+import io.quarkus.security.identity.request.TrustedAuthenticationRequest;
+import io.quarkus.vertx.http.runtime.security.ChallengeData;
+import io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism;
+import io.smallrye.mutiny.Uni;
+import io.vertx.ext.web.RoutingContext;
+
+public abstract class BaseHeaderAuthentication
+ implements HttpAuthenticationMechanism
+{
+
+ @Override
+ public Uni authenticate(
+ RoutingContext context,
+ IdentityProviderManager identityProviderManager
+ ) {
+ String role = context.request().getHeader(InternalValue.role);
+
+ System.out.println(
+ "HeaderRolesFilter: " +
+ role +
+ " - " +
+ context.request().headers().toString()
+ );
+
+ if (role != null && !role.isEmpty()) {
+ return identityProviderManager.authenticate(
+ new TrustedAuthenticationRequest(role)
+ );
+ }
+
+ return Uni.createFrom().nullItem();
+ }
+
+ @Override
+ public Uni getChallenge(RoutingContext context) {
+ return Uni.createFrom().nullItem();
+ }
+}
diff --git a/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java b/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java
deleted file mode 100644
index aee7b63..0000000
--- a/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.drinkool.lib.utils;
-
-import com.drinkool.InternalValue;
-import io.quarkus.security.identity.AuthenticationRequestContext;
-import io.quarkus.security.identity.IdentityProvider;
-import io.quarkus.security.identity.SecurityIdentity;
-import io.quarkus.security.identity.request.TrustedAuthenticationRequest;
-import io.quarkus.security.runtime.QuarkusSecurityIdentity;
-import io.smallrye.mutiny.Uni;
-import io.vertx.core.http.HttpServerRequest;
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-
-@ApplicationScoped
-public class HeaderIdentityProvider
- implements IdentityProvider
-{
-
- @Inject
- HttpServerRequest httpServerRequest;
-
- @Override
- public Class getRequestType() {
- return TrustedAuthenticationRequest.class;
- }
-
- @Override
- public Uni authenticate(
- TrustedAuthenticationRequest request,
- AuthenticationRequestContext context
- ) {
- String role = httpServerRequest.getHeader(InternalValue.role);
-
- return Uni.createFrom().item(
- QuarkusSecurityIdentity.builder().addRole(role).build()
- );
- }
-}