diff --git a/src/main/java/iudx/apd/acl/server/aaaService/AuthClient.java b/src/main/java/iudx/apd/acl/server/aaaService/AuthClient.java index 4c6552c6..ce1ed2d0 100644 --- a/src/main/java/iudx/apd/acl/server/aaaService/AuthClient.java +++ b/src/main/java/iudx/apd/acl/server/aaaService/AuthClient.java @@ -1,4 +1,4 @@ -package iudx.apd.acl.server.authentication; +package iudx.apd.acl.server.aaaService; import static iudx.apd.acl.server.apiserver.util.Constants.EMAIL_ID; import static iudx.apd.acl.server.apiserver.util.Constants.FIRST_NAME; diff --git a/src/main/java/iudx/apd/acl/server/aaaService/AuthClientInterface.java b/src/main/java/iudx/apd/acl/server/aaaService/AuthClientInterface.java index 063e96e4..a4d4dde8 100644 --- a/src/main/java/iudx/apd/acl/server/aaaService/AuthClientInterface.java +++ b/src/main/java/iudx/apd/acl/server/aaaService/AuthClientInterface.java @@ -1,4 +1,4 @@ -package iudx.apd.acl.server.authentication; +package iudx.apd.acl.server.aaaService; import io.vertx.core.Future; import io.vertx.core.json.JsonObject; diff --git a/src/main/java/iudx/apd/acl/server/apiserver/ApiServerVerticle.java b/src/main/java/iudx/apd/acl/server/apiserver/ApiServerVerticle.java index b3277918..54ad44d7 100644 --- a/src/main/java/iudx/apd/acl/server/apiserver/ApiServerVerticle.java +++ b/src/main/java/iudx/apd/acl/server/apiserver/ApiServerVerticle.java @@ -25,12 +25,14 @@ import io.vertx.ext.web.handler.CorsHandler; import io.vertx.ext.web.handler.TimeoutHandler; import io.vertx.ext.web.openapi.RouterBuilder; +import iudx.apd.acl.server.aaaService.AuthClient; import iudx.apd.acl.server.apiserver.util.User; import iudx.apd.acl.server.auditing.AuditingService; -import iudx.apd.acl.server.authentication.AuthClient; import iudx.apd.acl.server.authentication.AuthHandler; import iudx.apd.acl.server.authentication.Authentication; import iudx.apd.acl.server.authentication.AuthenticationService; +import iudx.apd.acl.server.authentication.VerifyAuthHandler; +import iudx.apd.acl.server.authentication.authorization.UserAccessHandler; import iudx.apd.acl.server.common.Api; import iudx.apd.acl.server.common.HttpStatusCode; import iudx.apd.acl.server.common.ResponseUrn; @@ -81,7 +83,9 @@ public class ApiServerVerticle extends AbstractVerticle { private PostgresService pgService; private WebClient webClient; private WebClientOptions webClientOptions; - private RoutingContextHelper routingContextHelper; + private AuthHandler authHandler; + private UserAccessHandler userAccessHandler; + private VerifyAuthHandler verifyAuthHandler; /** * This method is used to start the Verticle. It deploys a verticle in a cluster, reads the @@ -107,8 +111,11 @@ public void start() throws Exception { authenticator = AuthenticationService.createProxy(vertx, AUTH_SERVICE_ADDRESS); authClient = new AuthClient(config(), webClient); pgService = new PostgresService(config(), vertx); - routingContextHelper = new RoutingContextHelper(); FailureHandler failureHandler = new FailureHandler(); + authHandler = new AuthHandler(api, authenticator); + verifyAuthHandler = new VerifyAuthHandler(api, authenticator); + + userAccessHandler = new UserAccessHandler(pgService, authClient); /* Initialize Router builder */ RouterBuilder.create(vertx, "docs/openapi.yaml") @@ -118,49 +125,57 @@ public void start() throws Exception { routerBuilder .operation(CREATE_POLICY_API) - .handler(AuthHandler.create(api, authenticator, authClient, pgService, routingContextHelper)) + .handler(authHandler) + .handler(userAccessHandler) .handler(this::postPoliciesHandler) .failureHandler(failureHandler); routerBuilder .operation(GET_POLICY_API) - .handler(AuthHandler.create(api, authenticator, authClient, pgService, routingContextHelper)) + .handler(authHandler) + .handler(userAccessHandler) .handler(this::getPoliciesHandler) .failureHandler(failureHandler); routerBuilder .operation(DELETE_POLICY_API) - .handler(AuthHandler.create(api, authenticator, authClient, pgService, routingContextHelper)) + .handler(authHandler) + .handler(userAccessHandler) .handler(this::deletePoliciesHandler) .failureHandler(failureHandler); routerBuilder .operation(CREATE_NOTIFICATIONS_API) - .handler(AuthHandler.create(api, authenticator, authClient, pgService, routingContextHelper)) + .handler(authHandler) + .handler(userAccessHandler) .handler(this::postAccessRequestHandler) .failureHandler(failureHandler); routerBuilder .operation(UPDATE_NOTIFICATIONS_API) - .handler(AuthHandler.create(api, authenticator, authClient, pgService, routingContextHelper)) + .handler(authHandler) + .handler(userAccessHandler) .handler(this::putAccessRequestHandler) .failureHandler(failureHandler); routerBuilder .operation(GET_NOTIFICATIONS_API) - .handler(AuthHandler.create(api, authenticator, authClient, pgService, routingContextHelper)) + .handler(authHandler) + .handler(userAccessHandler) .handler(this::getAccessRequestHandler) .failureHandler(failureHandler); routerBuilder .operation(DELETE_NOTIFICATIONS_API) - .handler(AuthHandler.create(api, authenticator, authClient, pgService, routingContextHelper)) + .handler(authHandler) + .handler(userAccessHandler) .handler(this::deleteAccessRequestHandler) .failureHandler(failureHandler); routerBuilder .operation(VERIFY_API) - .handler(AuthHandler.create(api, authenticator, authClient, pgService, routingContextHelper)) + .handler(authHandler) + .handler(userAccessHandler) .handler(this::verifyRequestHandler) .failureHandler(failureHandler); @@ -231,7 +246,7 @@ private void verifyRequestHandler(RoutingContext routingContext) { private void postAccessRequestHandler(RoutingContext routingContext) { JsonObject request = routingContext.body().asJsonObject(); HttpServerResponse response = routingContext.response(); - User user = routingContextHelper.getUser(); + User user = RoutingContextHelper.getUser(routingContext); notificationService .createNotification(request, user) .onComplete( @@ -264,7 +279,7 @@ private void printDeployedEndpoints(Router router) { private void putAccessRequestHandler(RoutingContext routingContext) { JsonObject notification = routingContext.body().asJsonObject(); HttpServerResponse response = routingContext.response(); - User user = routingContextHelper.getUser(); + User user = RoutingContextHelper.getUser(routingContext); notificationService .updateNotification(notification, user) .onComplete( @@ -289,7 +304,7 @@ private void putAccessRequestHandler(RoutingContext routingContext) { private void deleteAccessRequestHandler(RoutingContext routingContext) { JsonObject notification = routingContext.body().asJsonObject(); HttpServerResponse response = routingContext.response(); - User user = routingContextHelper.getUser(); + User user = RoutingContextHelper.getUser(routingContext); notificationService .deleteNotification(notification, user) .onComplete( @@ -313,7 +328,7 @@ private void deleteAccessRequestHandler(RoutingContext routingContext) { private void getAccessRequestHandler(RoutingContext routingContext) { HttpServerResponse response = routingContext.response(); - User user = routingContextHelper.getUser(); + User user = RoutingContextHelper.getUser(routingContext); notificationService .getNotification(user) .onComplete( @@ -330,7 +345,7 @@ private void getAccessRequestHandler(RoutingContext routingContext) { private void postPoliciesHandler(RoutingContext routingContext) { JsonObject requestBody = routingContext.body().asJsonObject(); HttpServerResponse response = routingContext.response(); - User user = routingContextHelper.getUser(); + User user = RoutingContextHelper.getUser(routingContext); policyService .createPolicy(requestBody, user) .onComplete( @@ -351,7 +366,7 @@ private void deletePoliciesHandler(RoutingContext routingContext) { JsonObject policy = routingContext.body().asJsonObject(); HttpServerResponse response = routingContext.response(); - User user = routingContextHelper.getUser(); + User user = RoutingContextHelper.getUser(routingContext); policyService .deletePolicy(policy, user) .onComplete( @@ -376,7 +391,7 @@ private void deletePoliciesHandler(RoutingContext routingContext) { private void getPoliciesHandler(RoutingContext routingContext) { HttpServerResponse response = routingContext.response(); - User user = routingContextHelper.getUser(); + User user = RoutingContextHelper.getUser(routingContext); policyService .getPolicy(user) .onComplete( @@ -537,7 +552,7 @@ private Future handleAuditLogs(RoutingContext context) { LOGGER.debug("handleAuditLogs started"); HttpServerRequest request = context.request(); HttpServerResponse response = context.response(); - User user = routingContextHelper.getUser(); + User user = RoutingContextHelper.getUser(context); JsonObject requestBody = context.body().asJsonObject(); String userId = user.getUserId(); long size = response.bytesWritten(); diff --git a/src/main/java/iudx/apd/acl/server/authentication/AuthHandler.java b/src/main/java/iudx/apd/acl/server/authentication/AuthHandler.java index 1c0c60cd..ede61681 100644 --- a/src/main/java/iudx/apd/acl/server/authentication/AuthHandler.java +++ b/src/main/java/iudx/apd/acl/server/authentication/AuthHandler.java @@ -1,208 +1,60 @@ package iudx.apd.acl.server.authentication; import static iudx.apd.acl.server.apiserver.util.Constants.*; -import static iudx.apd.acl.server.authentication.Constants.*; -import static iudx.apd.acl.server.authentication.Constants.ROLE; -import static iudx.apd.acl.server.authentication.Constants.USER_ID; import static iudx.apd.acl.server.common.ResponseUrn.INVALID_TOKEN_URN; import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Promise; -import io.vertx.core.http.HttpServerRequest; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.RoutingContext; -import io.vertx.sqlclient.Row; -import io.vertx.sqlclient.Tuple; -import iudx.apd.acl.server.apiserver.util.User; +import iudx.apd.acl.server.authentication.model.JwtData; import iudx.apd.acl.server.common.Api; import iudx.apd.acl.server.common.HttpStatusCode; import iudx.apd.acl.server.common.ResponseUrn; import iudx.apd.acl.server.common.RoutingContextHelper; -import iudx.apd.acl.server.policy.PostgresService; -import java.util.UUID; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class AuthHandler implements Handler { - private static final Logger LOGGER = LogManager.getLogger(AuthHandler.class); static AuthenticationService authenticator; static Api api; - private static AuthClient authClient; - private static PostgresService pgService; - private static RoutingContextHelper contextHelper; - private HttpServerRequest request; + private final Logger LOGGER = LogManager.getLogger(AuthHandler.class); - public static AuthHandler create( + public AuthHandler( Api apis, - AuthenticationService authenticationService, - AuthClient client, - PostgresService postgresService, - RoutingContextHelper routingContextHelper) { + AuthenticationService authenticationService) { authenticator = authenticationService; api = apis; - authClient = client; - pgService = postgresService; - contextHelper = routingContextHelper; - return new AuthHandler(); } @Override public void handle(RoutingContext context) { - request = context.request(); - - String token = request.headers().get(AUTHORIZATION_KEY); - final String method = context.request().method().toString(); - final String path = getNormalizedPath(request.path()); - - JsonObject authInfo = - new JsonObject().put(API_ENDPOINT, path).put(HEADER_TOKEN, token).put(API_METHOD, method); - - if (path.equals(VERIFY_POLICY_API)) { - if (token.trim().split(" ").length == 2) { - token = token.trim().split(" ")[1]; - authInfo.put(HEADER_TOKEN, token); - Future verifyFuture = authenticator.tokenIntrospectForVerify(authInfo); - verifyFuture.onComplete( - verifyHandler -> { - if (verifyHandler.succeeded()) { - LOGGER.info("User Verified Successfully."); - context.next(); - } else if (verifyHandler.failed()) { - LOGGER.error("User Verification Failed. " + verifyHandler.cause().getMessage()); - processAuthFailure(context, verifyHandler.cause().getMessage()); - } - }); - } else { - processAuthFailure(context, "invalid token"); - } - } else { - checkIfAuth(authInfo) - .onSuccess( - userObj -> { - LOGGER.info("User Verified Successfully."); - contextHelper.setUser(context, userObj); - context.next(); - }) - .onFailure( - fail -> { - LOGGER.error("User Verification Failed. " + fail.getMessage()); - processAuthFailure(context, fail.getMessage()); - }); - } - } - - Future checkIfAuth(JsonObject authenticationInfo) { - Promise promise = Promise.promise(); - Future tokenIntrospect = authenticator.tokenIntrospect(authenticationInfo); - - Future getUserInfo = tokenIntrospect.compose(this::getUserInfo); - getUserInfo.onSuccess(promise::complete).onFailure(promise::fail); - return promise.future(); - } - - private Future getUserInfo(JsonObject jsonObject) { - LOGGER.info("Getting User Info."); - Promise promise = Promise.promise(); - Tuple tuple = Tuple.of(UUID.fromString(jsonObject.getString("userId"))); - UserContainer userContainer = new UserContainer(); - pgService - .getPool() - .withConnection( - sqlConnection -> - sqlConnection - .preparedQuery(GET_USER) - .execute(tuple) - .onFailure( - existingIdFailureHandler -> { - LOGGER.error( - "checkIfUserExist db fail {}", - existingIdFailureHandler.getLocalizedMessage()); - })) + RoutingContextHelper.setApis(context, api); + JsonObject authInfo = RoutingContextHelper.getAuthInfo(context); + checkIfAuth(authInfo) .onSuccess( - rows -> { - if (rows != null && rows.size() > 0) { - LOGGER.info("User found in db."); - Row row = rows.iterator().next(); - JsonObject result = row.toJson(); // Get the single row - JsonObject userObj = new JsonObject(); - userObj.put(USER_ID, jsonObject.getString(USER_ID)); - userObj.put(USER_ROLE, jsonObject.getString(ROLE)); - userObj.put(EMAIL_ID, result.getString("email_id")); - userObj.put(FIRST_NAME, result.getString("first_name")); - userObj.put(LAST_NAME, result.getString("last_name")); - userObj.put(RS_SERVER_URL, jsonObject.getString(AUD)); - // - // userObj.put(IS_DELEGATE,jsonObject.getBoolean(IS_DELEGATE)); - - User user = new User(userObj); - promise.complete(user); - } else { - LOGGER.info("Getting user from Auth"); - Future getUserFromAuth = authClient.fetchUserInfo(jsonObject); - Future insertIntoDb = - getUserFromAuth.compose( - userObj -> { - userContainer.user = userObj; - return insertUserIntoDb(userContainer.user); - }); - insertIntoDb - .onSuccess( - successHandler -> { - promise.complete(userContainer.user); - }) - .onFailure(promise::fail); - } + jwtData -> { + LOGGER.info("User Verified Successfully."); + RoutingContextHelper.setJwtData(context, jwtData); + context.next(); + }) + .onFailure( + fail -> { + LOGGER.error("User Verification Failed. " + fail.getMessage()); + processAuthFailure(context, fail.getMessage()); }); - return promise.future(); } - private Future insertUserIntoDb(User user) { - Promise promise = Promise.promise(); - Tuple tuple = - Tuple.of(user.getUserId(), user.getEmailId(), user.getFirstName(), user.getLastName()); + Future checkIfAuth(JsonObject authenticationInfo) { + Promise promise = Promise.promise(); + Future tokenIntrospect = authenticator.tokenIntrospect(authenticationInfo); - pgService - .getPool() - .withConnection( - sqlConnection -> - sqlConnection - .preparedQuery(INSERT_USER_TABLE) - .execute(tuple) - .onFailure( - existingIdFailureHandler -> { - LOGGER.error( - "insertUserIntoDb db fail {}", - existingIdFailureHandler.getLocalizedMessage()); - promise.fail(existingIdFailureHandler.getLocalizedMessage()); - }) - .onSuccess( - successHandler -> { - LOGGER.info("User inserted in db successfully."); - promise.complete(); - })); + // Future getUserInfo = tokenIntrospect.compose(this::getUserInfo); + tokenIntrospect.onSuccess(promise::complete).onFailure(promise::fail); return promise.future(); } - /** - * get normalized path without id as path param. - * - * @param url complete path from request - * @return path without id. - */ - private String getNormalizedPath(String url) { - LOGGER.debug("URL: " + url); - String[] urlsToMatch = {api.getPoliciesUrl(), api.getRequestPoliciesUrl(), api.getVerifyUrl()}; - - for (String apiUrl : urlsToMatch) { - if (url.matches(apiUrl)) { - return apiUrl; - } - } - - return null; - } - private void processAuthFailure(RoutingContext ctx, String failureMessage) { ResponseUrn responseUrn = INVALID_TOKEN_URN; HttpStatusCode statusCode = HttpStatusCode.getByValue(401); @@ -223,8 +75,4 @@ private JsonObject generateResponse(ResponseUrn urn, HttpStatusCode statusCode) .put(TITLE, statusCode.getDescription()) .put(DETAIL, statusCode.getDescription()); } - - static final class UserContainer { - User user; - } } diff --git a/src/main/java/iudx/apd/acl/server/authentication/AuthenticationService.java b/src/main/java/iudx/apd/acl/server/authentication/AuthenticationService.java index eba61d21..0806854d 100644 --- a/src/main/java/iudx/apd/acl/server/authentication/AuthenticationService.java +++ b/src/main/java/iudx/apd/acl/server/authentication/AuthenticationService.java @@ -6,6 +6,7 @@ import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.json.JsonObject; +import iudx.apd.acl.server.authentication.model.JwtData; /** * The Authentication Service. @@ -44,7 +45,7 @@ static AuthenticationService createProxy(Vertx vertx, String address) { * @param authenticationInfo which is a JsonObject containing token: String and apiEndpoint: * @return Future of JsonObject containing information from the decoded token */ - Future tokenIntrospect(JsonObject authenticationInfo); + Future tokenIntrospect(JsonObject authenticationInfo); /** * The tokenIntrospectForVerify method implements the authentication module for IUDX Verify APIs. diff --git a/src/main/java/iudx/apd/acl/server/authentication/JwtAuthenticationServiceImpl.java b/src/main/java/iudx/apd/acl/server/authentication/JwtAuthenticationServiceImpl.java index 3bb0e9d5..50ea573e 100644 --- a/src/main/java/iudx/apd/acl/server/authentication/JwtAuthenticationServiceImpl.java +++ b/src/main/java/iudx/apd/acl/server/authentication/JwtAuthenticationServiceImpl.java @@ -1,24 +1,11 @@ package iudx.apd.acl.server.authentication; -import static iudx.apd.acl.server.apiserver.util.Constants.API_ENDPOINT; -import static iudx.apd.acl.server.apiserver.util.Constants.API_METHOD; -import static iudx.apd.acl.server.authentication.Constants.AUD; -import static iudx.apd.acl.server.authentication.Constants.IS_DELEGATE; -import static iudx.apd.acl.server.authentication.Constants.ROLE; -import static iudx.apd.acl.server.authentication.Constants.USER_ID; -import static iudx.apd.acl.server.authentication.authorization.IudxRole.DELEGATE; - +import static iudx.apd.acl.server.apiserver.util.Constants.*; import io.vertx.core.Future; import io.vertx.core.Promise; import io.vertx.core.json.JsonObject; import io.vertx.ext.auth.authentication.TokenCredentials; import io.vertx.ext.auth.jwt.JWTAuth; -import iudx.apd.acl.server.authentication.authorization.AuthorizationContextFactory; -import iudx.apd.acl.server.authentication.authorization.AuthorizationRequest; -import iudx.apd.acl.server.authentication.authorization.AuthorizationStrategy; -import iudx.apd.acl.server.authentication.authorization.IudxRole; -import iudx.apd.acl.server.authentication.authorization.JwtAuthorization; -import iudx.apd.acl.server.authentication.authorization.Method; import iudx.apd.acl.server.authentication.model.JwtData; import iudx.apd.acl.server.common.Api; import org.apache.logging.log4j.LogManager; @@ -38,34 +25,35 @@ public JwtAuthenticationServiceImpl(final JWTAuth jwtAuth, final JsonObject conf this.apis = apis; } + @Override - public Future tokenIntrospect(JsonObject authenticationInfo) { - Promise promise = Promise.promise(); - String token = authenticationInfo.getString("token"); + public Future tokenIntrospect(JsonObject authenticationInfo) { + Promise promise = Promise.promise(); + String token = authenticationInfo.getString(HEADER_TOKEN); ResultContainer resultContainer = new ResultContainer(); Future jwtDecodeFuture = decodeJwt(token); - jwtDecodeFuture + + Future validateJwtAccessFuture = jwtDecodeFuture .compose( decodeHandler -> { resultContainer.jwtData = decodeHandler; return validateJwtAccess(resultContainer.jwtData); - }) - .compose(isValidJwtAccess -> validateAccess(resultContainer.jwtData, authenticationInfo)) - .onSuccess(promise::complete) - .onFailure( - failureHandler -> { - LOGGER.error("error : " + failureHandler.getMessage()); - promise.fail(failureHandler.getLocalizedMessage()); }); + validateJwtAccessFuture + .onSuccess(isValidJwt -> { + promise.complete(resultContainer.jwtData); + }).onFailure(failureHandler ->{ + LOGGER.error("error : " + failureHandler.getMessage()); + promise.fail(failureHandler.getLocalizedMessage()); + }); return promise.future(); } - @Override public Future tokenIntrospectForVerify(JsonObject authenticationInfo) { Promise promise = Promise.promise(); - String token = authenticationInfo.getString("token"); + String token = authenticationInfo.getString(HEADER_TOKEN); Future jwtDecodeFuture = decodeJwt(token); jwtDecodeFuture @@ -117,35 +105,6 @@ public Future validateJwtAccess(JwtData jwtData) { return promise.future(); } - Future validateAccess(JwtData jwtData, JsonObject authInfo) { - LOGGER.info("Authorization check started"); - Promise promise = Promise.promise(); - Method method = Method.valueOf(authInfo.getString(API_METHOD)); - String api = authInfo.getString(API_ENDPOINT); - AuthorizationRequest authRequest = new AuthorizationRequest(method, api); - - IudxRole role = IudxRole.fromRole(jwtData); - - AuthorizationStrategy authStrategy = AuthorizationContextFactory.create(role, apis); - LOGGER.info("strategy : " + authStrategy.getClass().getSimpleName()); - - JwtAuthorization jwtAuthStrategy = new JwtAuthorization(authStrategy); - if (jwtAuthStrategy.isAuthorized(authRequest)) { - JsonObject jsonResponse = new JsonObject(); - boolean isDelegate = jwtData.getRole().equalsIgnoreCase(DELEGATE.getRole()); - jsonResponse.put(USER_ID, isDelegate ? jwtData.getDid() : jwtData.getSub()); - jsonResponse.put(IS_DELEGATE, isDelegate); - jsonResponse.put(ROLE, role); - jsonResponse.put(AUD, jwtData.getAud()); - promise.complete(jsonResponse); - } else { - LOGGER.info("Failed in authorization check."); - JsonObject result = new JsonObject().put("401", "no access provided to endpoint"); - promise.fail(result.toString()); - } - return promise.future(); - } - public Future decodeJwt(String jwtToken) { Promise promise = Promise.promise(); TokenCredentials creds = new TokenCredentials(jwtToken); diff --git a/src/main/java/iudx/apd/acl/server/authentication/VerifyAuthHandler.java b/src/main/java/iudx/apd/acl/server/authentication/VerifyAuthHandler.java new file mode 100644 index 00000000..9186e655 --- /dev/null +++ b/src/main/java/iudx/apd/acl/server/authentication/VerifyAuthHandler.java @@ -0,0 +1,76 @@ +package iudx.apd.acl.server.authentication; + +import static iudx.apd.acl.server.apiserver.util.Constants.*; +import static iudx.apd.acl.server.apiserver.util.Constants.DETAIL; +import static iudx.apd.acl.server.common.ResponseUrn.INVALID_TOKEN_URN; + +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.RoutingContext; +import iudx.apd.acl.server.common.Api; +import iudx.apd.acl.server.common.HttpStatusCode; +import iudx.apd.acl.server.common.ResponseUrn; +import iudx.apd.acl.server.common.RoutingContextHelper; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class VerifyAuthHandler implements Handler { + static AuthenticationService authenticator; + static Api api; + private final Logger LOGGER = LogManager.getLogger(VerifyAuthHandler.class); + + public VerifyAuthHandler( + Api apis, + AuthenticationService authenticationService + ) { + authenticator = authenticationService; + api = apis; + } + + @Override + public void handle(RoutingContext context) { + RoutingContextHelper.setApis(context, api); + String token = RoutingContextHelper.getToken(context); + JsonObject authInfo = RoutingContextHelper.getAuthInfo(context); + + if (token.trim().split(" ").length == 2) { + token = token.trim().split(" ")[1]; + authInfo.put(HEADER_TOKEN, token); + Future verifyFuture = authenticator.tokenIntrospectForVerify(authInfo); + verifyFuture.onComplete( + verifyHandler -> { + if (verifyHandler.succeeded()) { + LOGGER.info("User Verified Successfully."); + context.next(); + } else if (verifyHandler.failed()) { + LOGGER.error("User Verification Failed. " + verifyHandler.cause().getMessage()); + processAuthFailure(context, verifyHandler.cause().getMessage()); + } + }); + } else { + processAuthFailure(context, "invalid token"); + } + } + + private void processAuthFailure(RoutingContext ctx, String failureMessage) { + ResponseUrn responseUrn = INVALID_TOKEN_URN; + HttpStatusCode statusCode = HttpStatusCode.getByValue(401); + if (failureMessage.equalsIgnoreCase("User information is invalid")) { + responseUrn = ResponseUrn.INTERNAL_SERVER_ERROR; + statusCode = HttpStatusCode.INTERNAL_SERVER_ERROR; + } + LOGGER.error("Error : Authentication Failure"); + ctx.response() + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .setStatusCode(statusCode.getValue()) + .end(generateResponse(responseUrn, statusCode).toString()); + } + + private JsonObject generateResponse(ResponseUrn urn, HttpStatusCode statusCode) { + return new JsonObject() + .put(TYPE, urn.getUrn()) + .put(TITLE, statusCode.getDescription()) + .put(DETAIL, statusCode.getDescription()); + } +} diff --git a/src/main/java/iudx/apd/acl/server/authentication/authorization/AuthorizationContextFactory.java b/src/main/java/iudx/apd/acl/server/authentication/authorization/AuthorizationContextFactory.java index 66b230fb..0c2e40f1 100644 --- a/src/main/java/iudx/apd/acl/server/authentication/authorization/AuthorizationContextFactory.java +++ b/src/main/java/iudx/apd/acl/server/authentication/authorization/AuthorizationContextFactory.java @@ -4,7 +4,7 @@ public class AuthorizationContextFactory { - public static AuthorizationStrategy create(IudxRole role, Api apis) { + public static AuthorizationStrategy create(DxRole role, Api apis) { if (role == null) { throw new IllegalArgumentException(role + "role is not defined in IUDX"); diff --git a/src/main/java/iudx/apd/acl/server/authentication/authorization/DxRole.java b/src/main/java/iudx/apd/acl/server/authentication/authorization/DxRole.java index 210468e0..457f8613 100644 --- a/src/main/java/iudx/apd/acl/server/authentication/authorization/DxRole.java +++ b/src/main/java/iudx/apd/acl/server/authentication/authorization/DxRole.java @@ -3,12 +3,12 @@ import iudx.apd.acl.server.authentication.model.JwtData; import java.util.stream.Stream; -public enum IudxRole { +public enum DxRole { CONSUMER("consumer"), PROVIDER("provider"), DELEGATE("delegate"); private final String role; - IudxRole(String role) { + DxRole(String role) { this.role = role; } @@ -16,7 +16,7 @@ public String getRole() { return this.role; } - public static IudxRole fromRole(final JwtData jwtData) { + public static DxRole fromRole(final JwtData jwtData) { String role = jwtData.getRole().equalsIgnoreCase(DELEGATE.getRole()) ? jwtData.getDrl() : jwtData.getRole(); return Stream.of(values()) .filter(v -> v.role.equalsIgnoreCase(role)) diff --git a/src/main/java/iudx/apd/acl/server/authentication/authorization/UserAccessHandler.java b/src/main/java/iudx/apd/acl/server/authentication/authorization/UserAccessHandler.java new file mode 100644 index 00000000..e5a3fc1e --- /dev/null +++ b/src/main/java/iudx/apd/acl/server/authentication/authorization/UserAccessHandler.java @@ -0,0 +1,203 @@ +package iudx.apd.acl.server.authentication.authorization; + +import static iudx.apd.acl.server.apiserver.util.Constants.*; +import static iudx.apd.acl.server.apiserver.util.Constants.ROLE; +import static iudx.apd.acl.server.apiserver.util.Constants.USER_ID; +import static iudx.apd.acl.server.authentication.Constants.*; +import static iudx.apd.acl.server.authentication.Constants.AUD; +import static iudx.apd.acl.server.authentication.authorization.DxRole.DELEGATE; +import static iudx.apd.acl.server.common.ResponseUrn.INVALID_TOKEN_URN; + +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.core.Promise; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.RoutingContext; +import io.vertx.sqlclient.Row; +import io.vertx.sqlclient.Tuple; +import iudx.apd.acl.server.apiserver.util.User; +import iudx.apd.acl.server.aaaService.AuthClient; +import iudx.apd.acl.server.authentication.model.JwtData; +import iudx.apd.acl.server.common.Api; +import iudx.apd.acl.server.common.HttpStatusCode; +import iudx.apd.acl.server.common.ResponseUrn; +import iudx.apd.acl.server.common.RoutingContextHelper; +import iudx.apd.acl.server.policy.PostgresService; +import java.util.UUID; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class UserAccessHandler implements Handler { + private static final Logger LOGGER = LogManager.getLogger(UserAccessHandler.class); + private final PostgresService pgService; + private final AuthClient authClient; + public UserAccessHandler(PostgresService postgresService, AuthClient client) + { + authClient = client; + pgService = postgresService; + } + /** + * After JWT Authentication, User Access Validation is handled here + * + * @param event the event to handle + */ + @Override + public void handle(RoutingContext event) { + Future validateUserAccessFuture = validateAccess(event); + Future getUserInfoFuture = validateUserAccessFuture.compose(this::getUserInfo); + getUserInfoFuture.onComplete(handler -> { + if(handler.succeeded()) + { + /* set user in routing context */ + RoutingContextHelper.setUser(event, handler.result()); + event.next(); + } + else + { + LOGGER.error("User info fetch, access validation failed : {}",handler.cause().getMessage()); + processAuthorizationFailure(event, handler.cause().getMessage()); + } + }); + + } + + public Future validateAccess(RoutingContext event){ + LOGGER.info("Authorization check started"); + Promise promise = Promise.promise(); + Method method = Method.valueOf(RoutingContextHelper.getMethod(event)); + String api = RoutingContextHelper.getRequestPath(event); + AuthorizationRequest authRequest = new AuthorizationRequest(method, api); + JwtData jwtData = RoutingContextHelper.getJwtData(event); + DxRole role = DxRole.fromRole(jwtData); + Api apis = RoutingContextHelper.getApis(event); + LOGGER.info("api : {}", api.toString()); + + AuthorizationStrategy authStrategy = AuthorizationContextFactory.create(role, apis); + LOGGER.info("strategy : " + authStrategy.getClass().getSimpleName()); + + JwtAuthorization jwtAuthStrategy = new JwtAuthorization(authStrategy); + if (jwtAuthStrategy.isAuthorized(authRequest)) { + JsonObject jsonResponse = new JsonObject(); + boolean isDelegate = jwtData.getRole().equalsIgnoreCase(DELEGATE.getRole()); + jsonResponse.put(USER_ID, isDelegate ? jwtData.getDid() : jwtData.getSub()); + jsonResponse.put(IS_DELEGATE, isDelegate); + jsonResponse.put(ROLE, role); + jsonResponse.put(AUD, jwtData.getAud()); + promise.complete(jsonResponse); + } else { + LOGGER.info("Failed in authorization check."); + JsonObject result = new JsonObject().put("401", "no access provided to endpoint"); + promise.fail(result.toString()); + } + return promise.future(); + } + + private Future getUserInfo(JsonObject jsonObject) { + LOGGER.info("Getting User Info."); + Promise promise = Promise.promise(); + Tuple tuple = Tuple.of(UUID.fromString(jsonObject.getString("userId"))); + UserAccessHandler.UserContainer userContainer = new UserAccessHandler.UserContainer(); + pgService + .getPool() + .withConnection( + sqlConnection -> + sqlConnection + .preparedQuery(GET_USER) + .execute(tuple) + .onFailure( + existingIdFailureHandler -> { + LOGGER.error( + "checkIfUserExist db fail {}", + existingIdFailureHandler.getLocalizedMessage()); + })) + .onSuccess( + rows -> { + if (rows != null && rows.size() > 0) { + LOGGER.info("User found in db."); + Row row = rows.iterator().next(); + JsonObject result = row.toJson(); // Get the single row + JsonObject userObj = new JsonObject(); + userObj.put(USER_ID, jsonObject.getString(USER_ID)); + userObj.put(USER_ROLE, jsonObject.getString(ROLE)); + userObj.put(EMAIL_ID, result.getString("email_id")); + userObj.put(FIRST_NAME, result.getString("first_name")); + userObj.put(LAST_NAME, result.getString("last_name")); + userObj.put(RS_SERVER_URL, jsonObject.getString(AUD)); + // + // userObj.put(IS_DELEGATE,jsonObject.getBoolean(IS_DELEGATE)); + + LOGGER.info("user ashadfadfhkadf : " + userObj.encodePrettily()); + User user = new User(userObj); + promise.complete(user); + } else { + LOGGER.info("Getting user from Auth"); + Future getUserFromAuth = authClient.fetchUserInfo(jsonObject); + Future insertIntoDb = + getUserFromAuth.compose( + userObj -> { + userContainer.user = userObj; + return insertUserIntoDb(userContainer.user); + }); + insertIntoDb + .onSuccess( + successHandler -> { + promise.complete(userContainer.user); + }) + .onFailure(promise::fail); + } + }); + return promise.future(); + } + + private Future insertUserIntoDb(User user) { + Promise promise = Promise.promise(); + Tuple tuple = + Tuple.of(user.getUserId(), user.getEmailId(), user.getFirstName(), user.getLastName()); + + pgService + .getPool() + .withConnection( + sqlConnection -> + sqlConnection + .preparedQuery(INSERT_USER_TABLE) + .execute(tuple) + .onFailure( + existingIdFailureHandler -> { + LOGGER.error( + "insertUserIntoDb db fail {}", + existingIdFailureHandler.getLocalizedMessage()); + promise.fail(existingIdFailureHandler.getLocalizedMessage()); + }) + .onSuccess( + successHandler -> { + LOGGER.info("User inserted in db successfully."); + promise.complete(); + })); + return promise.future(); + } + + private void processAuthorizationFailure(RoutingContext ctx, String failureMessage) { + ResponseUrn responseUrn = INVALID_TOKEN_URN; + HttpStatusCode statusCode = HttpStatusCode.getByValue(401); + if (failureMessage.equalsIgnoreCase("User information is invalid")) { + responseUrn = ResponseUrn.INTERNAL_SERVER_ERROR; + statusCode = HttpStatusCode.INTERNAL_SERVER_ERROR; + } + LOGGER.error("Error : Authentication Failure"); + ctx.response() + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .setStatusCode(statusCode.getValue()) + .end(generateResponse(responseUrn, statusCode).toString()); + } + + private JsonObject generateResponse(ResponseUrn urn, HttpStatusCode statusCode) { + return new JsonObject() + .put(TYPE, urn.getUrn()) + .put(TITLE, statusCode.getDescription()) + .put(DETAIL, statusCode.getDescription()); + } + + static final class UserContainer { + User user; + } +} diff --git a/src/main/java/iudx/apd/acl/server/common/Api.java b/src/main/java/iudx/apd/acl/server/common/Api.java index f2f4a6a1..2d2cabb7 100644 --- a/src/main/java/iudx/apd/acl/server/common/Api.java +++ b/src/main/java/iudx/apd/acl/server/common/Api.java @@ -45,4 +45,14 @@ public String getRequestPoliciesUrl() { public String getVerifyUrl() { return verifyUrl.toString(); } + + @Override + public String toString() { + return "Api{" + + "dxApiBasePath='" + dxApiBasePath + '\'' + + ", policiesUrl=" + policiesUrl + + ", verifyUrl=" + verifyUrl + + ", requestPoliciesUrl=" + requestPoliciesUrl + + '}'; + } } diff --git a/src/main/java/iudx/apd/acl/server/common/RoutingContextHelper.java b/src/main/java/iudx/apd/acl/server/common/RoutingContextHelper.java index ef5d8a52..ccd7a37d 100644 --- a/src/main/java/iudx/apd/acl/server/common/RoutingContextHelper.java +++ b/src/main/java/iudx/apd/acl/server/common/RoutingContextHelper.java @@ -1,20 +1,70 @@ package iudx.apd.acl.server.common; -import static iudx.apd.acl.server.apiserver.util.Constants.USER; +import static iudx.apd.acl.server.apiserver.util.Constants.*; +import static iudx.apd.acl.server.apiserver.util.Constants.API_METHOD; +import io.vertx.core.json.JsonObject; import io.vertx.ext.web.RoutingContext; import iudx.apd.acl.server.apiserver.util.User; +import iudx.apd.acl.server.authentication.model.JwtData; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class RoutingContextHelper { - private RoutingContext routingContext; + private static final Logger LOGGER = LogManager.getLogger(RoutingContextHelper.class); + private static final String JWT_DATA = "jwtData"; - public void setUser(RoutingContext routingContext, User user) { + public static void setUser(RoutingContext routingContext, User user) { routingContext.put(USER, user); } - public User getUser() { + public static User getUser(RoutingContext routingContext) { return routingContext.get(USER); } + public static JsonObject getAuthInfo(RoutingContext routingContext){ + return + new JsonObject() + .put(API_ENDPOINT, getRequestPath(routingContext)) + .put(HEADER_TOKEN, getToken(routingContext)) + .put(API_METHOD, getMethod(routingContext)); + } + + public static String getToken(RoutingContext routingContext) + { + return routingContext.request().headers().get(AUTHORIZATION_KEY); + } + + public static String getMethod(RoutingContext routingContext) + { + return routingContext.request().method().toString(); + } + + public static String getRequestPath(RoutingContext routingContext) + { + return routingContext.request().path(); + } + + public static void setJwtData(RoutingContext routingContext, JwtData jwtData) + { + routingContext.put(JWT_DATA, jwtData); + } + + public static JwtData getJwtData(RoutingContext routingContext) + { + return routingContext.get(JWT_DATA); + } + + public static void setApis(RoutingContext routingContext, Api api) + { + routingContext.put(API, api); + } + + public static Api getApis(RoutingContext routingContext) + { + return routingContext.get(API); + } + + } diff --git a/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java b/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java index f42b87f0..5aa127e6 100644 --- a/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java @@ -26,7 +26,7 @@ import io.vertx.sqlclient.Tuple; import iudx.apd.acl.server.apiserver.util.ResourceObj; import iudx.apd.acl.server.apiserver.util.User; -import iudx.apd.acl.server.authentication.AuthClient; +import iudx.apd.acl.server.aaaService.AuthClient; import iudx.apd.acl.server.common.HttpStatusCode; import iudx.apd.acl.server.common.ResponseUrn; import iudx.apd.acl.server.policy.CatalogueClient; diff --git a/src/main/java/iudx/apd/acl/server/notification/NotificationVerticle.java b/src/main/java/iudx/apd/acl/server/notification/NotificationVerticle.java index d218e22a..09fda71d 100644 --- a/src/main/java/iudx/apd/acl/server/notification/NotificationVerticle.java +++ b/src/main/java/iudx/apd/acl/server/notification/NotificationVerticle.java @@ -6,7 +6,7 @@ import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClientOptions; import io.vertx.serviceproxy.ServiceBinder; -import iudx.apd.acl.server.authentication.AuthClient; +import iudx.apd.acl.server.aaaService.AuthClient; import iudx.apd.acl.server.policy.CatalogueClient; import iudx.apd.acl.server.policy.PostgresService; diff --git a/src/main/java/iudx/apd/acl/server/policy/GetPolicy.java b/src/main/java/iudx/apd/acl/server/policy/GetPolicy.java index fd3dbaf6..b09de717 100644 --- a/src/main/java/iudx/apd/acl/server/policy/GetPolicy.java +++ b/src/main/java/iudx/apd/acl/server/policy/GetPolicy.java @@ -45,6 +45,7 @@ public GetPolicy(PostgresService postgresService) { } public Future initiateGetPolicy(User user) { + Role role = user.getUserRole(); switch (role) { case CONSUMER_DELEGATE: diff --git a/src/test/java/iudx/apd/acl/server/authenticator/JwtAuthServiceImplTest.java b/src/test/java/iudx/apd/acl/server/authenticator/JwtAuthServiceImplTest.java index 79bc2801..1e27915a 100644 --- a/src/test/java/iudx/apd/acl/server/authenticator/JwtAuthServiceImplTest.java +++ b/src/test/java/iudx/apd/acl/server/authenticator/JwtAuthServiceImplTest.java @@ -24,12 +24,14 @@ import iudx.apd.acl.server.authentication.JwtAuthenticationServiceImpl; import iudx.apd.acl.server.authentication.model.JwtData; import iudx.apd.acl.server.common.Api; +import iudx.apd.acl.server.common.RoutingContextHelper; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith({VertxExtension.class, MockitoExtension.class}) @@ -59,6 +61,7 @@ static void init(Vertx vertx, VertxTestContext testContext) { JWTAuth jwtAuth = JWTAuth.create(vertx, jwtAuthOptions); + RoutingContextHelper routingContextHelper = new RoutingContextHelper(); jwtAuthenticationService = new JwtAuthenticationServiceImpl(jwtAuth, authConfig, apis); LOGGER.info("Auth tests setup complete"); @@ -95,7 +98,7 @@ public void allow4ConsumerDelegateIdentityToken(VertxTestContext testContext) { .onComplete( handler -> { if (handler.succeeded()) { - JsonObject result = handler.result(); + JsonObject result = handler.result().toJson(); assertEquals(Role.CONSUMER.getRole(), result.getString("role").toLowerCase()); assertEquals(true, result.getBoolean("isDelegate")); testContext.completeNow(); @@ -134,9 +137,9 @@ public void allow4ProviderDelegateIdentityToken(VertxTestContext testContext) { .onComplete( handler -> { if (handler.succeeded()) { - JsonObject result = handler.result(); - assertEquals(Role.PROVIDER.getRole(), result.getString("role").toLowerCase()); - assertEquals(true, result.getBoolean("isDelegate")); + JsonObject result = handler.result().toJson(); + assertEquals(Role.PROVIDER.getRole(), result.getString("drl").toLowerCase()); + assertEquals("delegate", result.getString("role")); testContext.completeNow(); } else { testContext.failNow("invalid access"); @@ -192,6 +195,7 @@ public void invalidRequestOfProviderPostNotification(VertxTestContext testContex .tokenIntrospect(authConfig) .onComplete( handler -> { + LOGGER.info("result is : " + handler); if (handler.succeeded()) { testContext.failNow("invalid access"); } else { diff --git a/src/test/java/iudx/apd/acl/server/authorization/TestAuthClient.java b/src/test/java/iudx/apd/acl/server/authorization/TestAuthClient.java index 19d45078..974fb9ee 100644 --- a/src/test/java/iudx/apd/acl/server/authorization/TestAuthClient.java +++ b/src/test/java/iudx/apd/acl/server/authorization/TestAuthClient.java @@ -17,7 +17,7 @@ import iudx.apd.acl.server.Utility; import iudx.apd.acl.server.apiserver.util.Role; import iudx.apd.acl.server.apiserver.util.User; -import iudx.apd.acl.server.authentication.AuthClient; +import iudx.apd.acl.server.aaaService.AuthClient; import iudx.apd.acl.server.authentication.AuthHandler; import iudx.apd.acl.server.authentication.AuthenticationService; import iudx.apd.acl.server.common.Api; diff --git a/src/test/java/iudx/apd/acl/server/authorization/TestAuthHandler.java b/src/test/java/iudx/apd/acl/server/authorization/TestAuthHandler.java index f3612bca..e9cc3e59 100644 --- a/src/test/java/iudx/apd/acl/server/authorization/TestAuthHandler.java +++ b/src/test/java/iudx/apd/acl/server/authorization/TestAuthHandler.java @@ -14,12 +14,12 @@ import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; import io.vertx.pgclient.PgPool; -import io.vertx.sqlclient.Tuple; import iudx.apd.acl.server.Utility; import iudx.apd.acl.server.apiserver.util.User; -import iudx.apd.acl.server.authentication.AuthClient; +import iudx.apd.acl.server.aaaService.AuthClient; import iudx.apd.acl.server.authentication.AuthHandler; import iudx.apd.acl.server.authentication.AuthenticationService; +import iudx.apd.acl.server.authentication.model.JwtData; import iudx.apd.acl.server.common.Api; import iudx.apd.acl.server.common.RoutingContextHelper; import iudx.apd.acl.server.policy.PostgresService; @@ -107,8 +107,7 @@ public AsyncResult answer(InvocationOnMock arg2) throws Throwable { if (handler.succeeded()) { owner = getOwner(); consumer = getConsumer(); - authHandler = - AuthHandler.create(api, authenticationService, client, postgresService, routingContextHelper); + authHandler = new AuthHandler(api, authenticationService); assertNotNull(authHandler); LOG.info("Set up the environment for testing successfully"); vertxTestContext.completeNow(); @@ -213,10 +212,11 @@ public void testHandleMethodForOtherEndpoints(VertxTestContext vertxTestContext) .put("userId", utility.getConsumerId()) .put(ROLE, "consumer") .put(AUD, "someDummyValue"); + JwtData jwtData = mock(JwtData.class); when(httpServerRequest.path()).thenReturn(api.getRequestPoliciesUrl()); when(authenticationService.tokenIntrospect(any())) - .thenReturn(Future.succeededFuture(jsonObject)); + .thenReturn(Future.succeededFuture(jwtData)); authHandler.handle(routingContext); @@ -294,13 +294,14 @@ public void testGetUserInfoWithAuthFailure(VertxTestContext vertxTestContext) { .put("firstName", firstName) .put("lastName", lastName) .put(AUD, "someDummyValue"); + JwtData jwtData = mock(JwtData.class); lenient() .when(client.fetchUserInfo(any())) .thenReturn(Future.failedFuture("Something went wrong...")); when(httpServerRequest.path()).thenReturn(api.getRequestPoliciesUrl()); when(authenticationService.tokenIntrospect(any())) - .thenReturn(Future.succeededFuture(jsonObject)); + .thenReturn(Future.succeededFuture(jwtData)); lenient().when(routingContext.response()).thenReturn(httpServerResponse); authHandler.handle(routingContext); diff --git a/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java b/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java index de55b5a6..11e6a2b3 100644 --- a/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java +++ b/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java @@ -20,7 +20,7 @@ import iudx.apd.acl.server.Utility; import iudx.apd.acl.server.apiserver.util.ResourceObj; import iudx.apd.acl.server.apiserver.util.User; -import iudx.apd.acl.server.authentication.AuthClient; +import iudx.apd.acl.server.aaaService.AuthClient; import iudx.apd.acl.server.common.HttpStatusCode; import iudx.apd.acl.server.common.ResponseUrn; import iudx.apd.acl.server.policy.CatalogueClient;