Skip to content

Commit

Permalink
Merge pull request #32 from gopal-mahajan/token-flow
Browse files Browse the repository at this point in the history
RMQ flow and Revoke token
  • Loading branch information
kailash authored Mar 29, 2022
2 parents ce6363c + 39ee2d5 commit d852a13
Show file tree
Hide file tree
Showing 24 changed files with 1,225 additions and 17 deletions.
30 changes: 30 additions & 0 deletions configs/config-dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@
"meteringDatabaseUserName": "",
"meteringDatabasePassword": "",
"meteringPoolSize": 25
},
{
"id":"iudx.gis.server.database.postgres.PostgresVerticle",
"verticleInstances": 1,
"databaseIp": "",
"databasePort": 1234,
"databaseName": "",
"databaseUserName": "",
"databasePassword": "",
"poolSize": 25

}, {
"id": "iudx.gis.server.databroker.DataBrokerVerticle",
"verticleInstances": 1,
"dataBrokerIP": "",
"dataBrokerPort": 5468,
"dataBrokerUserName": "",
"dataBrokerVhost": "",
"dataBrokerPassword": "",
"dataBrokerManagementPort": 30042,
"connectionTimeout": 6000,
"requestedHeartbeat": 60,
"handshakeTimeout": 6000,
"requestedChannelMax": 5,
"networkRecoveryInterval": 500,
"automaticRecoveryEnabled": true
},
{
"id": "iudx.gis.server.cache.CacheVerticle",
"verticleInstances": 1
}
]
}
34 changes: 32 additions & 2 deletions configs/config-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{
"id": "iudx.gis.server.apiserver.ApiServerVerticle",
"ssl": true,
"port":123,
"port":12344,
"production": false,
"keystore": "",
"keystorePassword": "",
Expand Down Expand Up @@ -45,7 +45,37 @@
"meteringDatabaseName": "",
"meteringDatabaseUserName": "",
"meteringDatabasePassword": "",
"meteringPoolSize": 25
"meteringPoolSize": 25},
{
"id":"iudx.gis.server.database.postgres.PostgresVerticle",
"verticleInstances": 1,
"databaseIp": "",
"databasePort": 1234,
"databaseName": "",
"databaseUserName": "",
"databasePassword": "",
"poolSize": 25

}, {
"id": "iudx.gis.server.databroker.DataBrokerVerticle",
"verticleInstances": 1,
"dataBrokerIP": "",
"dataBrokerPort": 1,
"dataBrokerUserName": "",
"dataBrokerVhost": "",
"dataBrokerPassword": "",
"dataBrokerManagementPort": 1,
"connectionTimeout": 1,
"requestedHeartbeat": 0,
"handshakeTimeout": 0,
"requestedChannelMax": 1,
"networkRecoveryInterval": 2,
"automaticRecoveryEnabled": true

},
{
"id": "iudx.gis.server.cache.CacheVerticle",
"verticleInstances": 1
}
]
}
32 changes: 31 additions & 1 deletion configs/config-test.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{
"id": "iudx.gis.server.apiserver.ApiServerVerticle",
"ssl": true,
"port":123,
"port":12344,
"production": false,
"keystore": "",
"keystorePassword": "",
Expand Down Expand Up @@ -46,6 +46,36 @@
"meteringDatabaseUserName": "",
"meteringDatabasePassword": "",
"meteringPoolSize": 25
},
{
"id":"iudx.gis.server.database.postgres.PostgresVerticle",
"verticleInstances": 1,
"databaseIp": "",
"databasePort": 1234,
"databaseName": "",
"databaseUserName": "",
"databasePassword": "",
"poolSize": 25

}, {
"id": "iudx.gis.server.databroker.DataBrokerVerticle",
"verticleInstances": 1,
"dataBrokerIP": "",
"dataBrokerPort": 5468,
"dataBrokerUserName": "",
"dataBrokerVhost": "",
"dataBrokerPassword": "",
"dataBrokerManagementPort": 30042,
"connectionTimeout": 6000,
"requestedHeartbeat": 60,
"handshakeTimeout": 6000,
"requestedChannelMax": 5,
"networkRecoveryInterval": 500,
"automaticRecoveryEnabled": true
},
{
"id": "iudx.gis.server.cache.CacheVerticle",
"verticleInstances": 1
}
]
}
20 changes: 19 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,30 @@
<groupId>io.vertx</groupId>
<artifactId>vertx-hazelcast</artifactId>
</dependency>

<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-rabbitmq-client</artifactId>

</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-zookeeper</artifactId>
<version>${hazelcast.version}</version>
</dependency>
<!-- -->

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package iudx.gis.server.authenticator;

import static iudx.gis.server.common.Constants.AUTHENTICATION_SERVICE_ADDRESS;
import static iudx.gis.server.common.Constants.CACHE_SERVICE_ADDRESS;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
Expand All @@ -12,6 +15,7 @@
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import io.vertx.serviceproxy.ServiceBinder;
import iudx.gis.server.cache.CacheService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand All @@ -28,12 +32,13 @@
*/
public class AuthenticationVerticle extends AbstractVerticle {

private static final String AUTH_SERVICE_ADDRESS = "iudx.gis.authentication.service";
private static final String AUTH_SERVICE_ADDRESS = AUTHENTICATION_SERVICE_ADDRESS;
private static final Logger LOGGER = LogManager.getLogger(AuthenticationVerticle.class);
private AuthenticationService jwtAuthenticationService;
private ServiceBinder binder;
private MessageConsumer<JsonObject> consumer;
private WebClient webClient;
private CacheService cacheService;

static WebClient createWebClient(Vertx vertx, JsonObject config) {
return createWebClient(vertx, config, false);
Expand Down Expand Up @@ -79,8 +84,8 @@ public void start() throws Exception {
"JWT ignore expiration set to true, do not set IgnoreExpiration in production!!");
}
JWTAuth jwtAuth = JWTAuth.create(vertx, jwtAuthOptions);

jwtAuthenticationService = new JwtAuthenticationServiceImpl(vertx, jwtAuth, config());
cacheService = CacheService.createProxy(vertx, CACHE_SERVICE_ADDRESS);
jwtAuthenticationService = new JwtAuthenticationServiceImpl(vertx, jwtAuth, config(),cacheService);

/* Publish the Authentication service with the Event Bus against an address. */
consumer =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@
import iudx.gis.server.authenticator.authorization.JwtAuthorization;
import iudx.gis.server.authenticator.authorization.Method;
import iudx.gis.server.authenticator.model.JwtData;
import iudx.gis.server.cache.CacheService;
import iudx.gis.server.cache.cacheImpl.CacheType;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpStatus;
Expand All @@ -49,6 +52,7 @@ public class JwtAuthenticationServiceImpl implements AuthenticationService {
final String path;
final String audience;
final String iss;
final CacheService cache;
// resourceIdCache will contain info about resources available(& their ACL) in resource server.
public Cache<String, String> resourceIdCache =
CacheBuilder.newBuilder()
Expand All @@ -62,14 +66,18 @@ public class JwtAuthenticationServiceImpl implements AuthenticationService {
.expireAfterAccess(Constants.CACHE_TIMEOUT_AMOUNT, TimeUnit.MINUTES)
.build();

public JwtAuthenticationServiceImpl(Vertx vertx, final JWTAuth jwtAuth, final JsonObject config) {
public JwtAuthenticationServiceImpl(
Vertx vertx,
final JWTAuth jwtAuth,
final JsonObject config,
final CacheService cacheService) {
this.jwtAuth = jwtAuth;
this.audience = config.getString("audience");
this.iss = config.getString("authServerHost");
this.host = config.getString("catServerHost");
this.port = config.getInteger("catServerPort");
this.path = Constants.CAT_RSG_PATH;

this.cache = cacheService;
WebClientOptions options = new WebClientOptions();
options.setTrustAll(true).setVerifyHost(false).setSsl(true);
catWebClient = WebClient.create(vertx, options);
Expand All @@ -93,7 +101,15 @@ public AuthenticationService tokenIntrospect(
result.jwtData = decodeHandler;
return isValidAudienceValue(result.jwtData);
})
.compose(audienceHandler -> isValidIid(result.jwtData))
.compose(
audienceHandler -> {
if (!result.jwtData.getIss().equals(result.jwtData.getSub())) {
return isRevokedClientToken(result.jwtData);
} else {
return Future.succeededFuture(true);
}
})
.compose(revokeClientTokenHandler -> isValidIid(result.jwtData))
.compose(IdHandler -> isValidRole(result.jwtData))
.onSuccess(successHandler -> handler.handle(Future.succeededFuture(successHandler)))
.onFailure(
Expand All @@ -106,7 +122,15 @@ public AuthenticationService tokenIntrospect(
result.jwtData = decodeHandler;
return isValidAudienceValue(result.jwtData);
})
.compose(audienceHandler -> isValidIssuerValue(result.jwtData))
.compose(
audienceHandler -> {
if (!result.jwtData.getIss().equals(result.jwtData.getSub())) {
return isRevokedClientToken(result.jwtData);
} else {
return Future.succeededFuture(true);
}
})
.compose(revokeClientTokenHandler -> isValidIssuerValue(result.jwtData))
.compose(
issuerHandler -> {
if (!result.jwtData.getIss().equals(result.jwtData.getSub())) {
Expand Down Expand Up @@ -277,7 +301,6 @@ Future<JsonObject> isValidRole(JwtData jwtData) {
Promise<JsonObject> promise = Promise.promise();
String jwtId = jwtData.getIid().split(":")[1];
String role = jwtData.getRole();
LOGGER.debug("ROLE " + role);
JsonObject jsonResponse = new JsonObject();
if (role.equalsIgnoreCase("admin")) {
jsonResponse.put(JSON_USERID, jwtData.getSub());
Expand Down Expand Up @@ -356,6 +379,42 @@ private Future<Boolean> isResourceExist(String id, String groupACL) {
return promise.future();
}

Future<Boolean> isRevokedClientToken(JwtData jwtData) {
LOGGER.trace("isRevokedClientToken started param : ");
Promise<Boolean> promise = Promise.promise();
CacheType cacheType = CacheType.REVOKED_CLIENT;
String subId = jwtData.getSub();
JsonObject requestJson = new JsonObject().put("type", cacheType).put("key", subId);

cache.get(
requestJson,
handler -> {
if (handler.succeeded()) {

JsonObject responseJson = handler.result();
String timestamp = responseJson.getString("value");

LocalDateTime revokedAt = ZonedDateTime.parse(timestamp).toLocalDateTime();
LocalDateTime jwtIssuedAt =
(LocalDateTime.ofInstant(
Instant.ofEpochSecond(jwtData.getIat()), ZoneId.systemDefault()));

if (jwtIssuedAt.isBefore(revokedAt)) {
LOGGER.error("Privileges for client are revoked.");
JsonObject result = new JsonObject().put("401", "revoked token passes");
promise.fail(result.toString());
} else {
promise.complete(true);
}
} else {
// since no value in cache, this means client_id is valid and not revoked
LOGGER.error("cache call result : [fail] " + handler.cause());
promise.complete(true);
}
});
return promise.future();
}

private Future<String> getGroupAccessPolicy(String groupId) {
LOGGER.trace("getGroupAccessPolicy() started");
Promise<String> promise = Promise.promise();
Expand Down
Loading

0 comments on commit d852a13

Please sign in to comment.