Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ $class=in.erail.common.FrameworkConfiguration
$scope=GLOBAL

redisClient=/io/vertx/redis/RedisClient
oAuth2Auth=/io/vertx/ext/auth/oauth2/OAuth2Auth
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ log=true
enable=true

allowedOrigin=*
allowedMethod=GET,POST,OPTIONS
allowedMethod=DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
allowedCredentials=false
maxAgeSeconds=86400
allowedHeaders=
allowedHeaders=Content-Type,Cache-Control,Authorization
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@
$class=in.erail.route.LoadUserFromAccessTokenRouteBuillder

vertx=/io/vertx/core/Vertx
authProvider=/io/vertx/ext/auth/jwt/JWTAuth
log=true
oAuth2Auth=/io/vertx/ext/auth/oauth2/OAuth2Auth
enable^=/in/erail/common/FrameworkConfiguration.oAuth2AuthEnable
8 changes: 8 additions & 0 deletions config-layers/common/io/vertx/ext/auth/jwt/JWTAuth.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#/io/vertx/ext/auth/jwt/JWTAuth
$class=io.vertx.reactivex.ext.auth.jwt.JWTAuth
$instanceFactory=/in/erail/factory/MethodInstanceFactory
$factory.class=io.vertx.reactivex.ext.auth.jwt.JWTAuth
$factory.method.name=create
$factory.param.values=/io/vertx/core/Vertx,/io/vertx/ext/auth/jwt/JWTAuthOptions
$factory.param.type=io.vertx.reactivex.core.Vertx,io.vertx.ext.auth.jwt.JWTAuthOptions
$factory.enable=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#/io/vertx/ext/auth/jwt/JWTAuthOptions
$class=io.vertx.ext.auth.jwt.JWTAuthOptions
$instanceFactory=/in/erail/factory/ParameterConstructorInstanceFactory
$constructor.param.values=jwtAuthOptionsConfig.json
$constructor.param.type=io.vertx.core.json.JsonObject
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"pubSecKeys" : [
{
"algorithm" : "RS256",
"publicKey" : "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr1MjI2WAw06VK8biQPC+0mVOkI4ZRt+327fxwrxyuu32AMPKznPCsKtRaI/Xma3+Yi09Dt99agkfUfw/rPr3N0Vcgzd1muhqZOe6vfWqmPCUUB263EkSa1GIx4pLZ3CfvAc3f24Y00CS+S0gjCIr7lwLelcL9Hu9eZg5sTEfzKB/3+yUJ875aYRGWXdM7DnNzODXKa9kc1EqWjwprX0UZwoo3OycgmYS+DyI/MHPcdWbilsjsw77ISFeBZ7OZ+hFJ/baABenAnsTwqbyvWlC6TS3GCXTeH10+0RGWvjJAZEPX0PEt626iMTqP61XEh8kpOROU/xmLWTKHz3EAcX+4QIDAQAB",
"secretKey" : "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCvUyMjZYDDTpUrxuJA8L7SZU6QjhlG37fbt/HCvHK67fYAw8rOc8Kwq1Foj9eZrf5iLT0O331qCR9R/D+s+vc3RVyDN3Wa6Gpk57q99aqY8JRQHbrcSRJrUYjHiktncJ+8Bzd/bhjTQJL5LSCMIivuXAt6Vwv0e715mDmxMR/MoH/f7JQnzvlphEZZd0zsOc3M4Ncpr2RzUSpaPCmtfRRnCijc7JyCZhL4PIj8wc9x1ZuKWyOzDvshIV4Fns5n6EUn9toAF6cCexPCpvK9aULpNLcYJdN4fXT7REZa+MkBkQ9fQ8S3rbqIxOo/rVcSHySk5E5T/GYtZMofPcQBxf7hAgMBAAECggEAGOlXNNBXW2jvCSlZPKD4fCyo3SFTth5ToYShdWoRYz4sli87wdnw7+lnx9Oobs2qN4j2BAb9avOg36VX5txCBDh2zK40p64eb/f9MMCXXOPSLxAKXQKE+3q6VJ/x1uDJ0Y209QZPwLSMLZub5E12sIejmd6EdFigs4ZNrD+upQRs6laM3EJdOqrHfArh18dJQoJcq3VfCCw1p+iPOJSVC6TS6Qp8nR/Qq2h5/5DnUj68RMg6jBLuaq+2vAvS/PXkUV5L0rJT11CoPzxusDDSJl7tkxI9Uzz7RfyZFzibxAmrUIxfqFIhQq+EnycYfKuTRDIZjYXvoKqatLhKtgkXgQKBgQDa2SGZJj6HmR25B4+xmJqpf9B1cM4yz4nOUy7xA80V5DRg/qol+T3SDjPXvoinR+fdgpqUBCxVyQHRWs05fDW/xkBXxalODlNSBWwhFBO2dvbdz3xWLDZJmm6rhgo7GZplTWEL6lxxNTwiKdkCLgW2CHkDpKxPy3x3P/50fM98MwKBgQDNFohdBKoiuG2H2qML27pifgJUJXg33YgUN3xPgR2V0UyVV7u1qq9aHiBL2oO+gp1Jz1N+aQQ6FVDGZ+Okg6VKPZKEZnfYP7AgUAPkqxtsI3oAYGt1OtcLoGXns+U8LxJkuwV3IilvdkMVGQa0rXHYn8pdK149yd+nWCCJL/cEmwKBgQCsL0fzAhcSgtLS4HMbDPEqyQhPTli9u3I2JlZ5hD8YqTrY0aU3SVltaoU5ioxj6Pwx2O8b5Aip2gOXHzT2tJZpc2buZ/MkGbtOfjur7urvlbv3mqa9+f0gfePzCfwEsck7SN1BDbx7yaGtU3WM9H7D0Pi9eBOmmHguLuhZ6FUq5wKBgEbjm/zzCM/5ibqkwyjtKW6z+aAWV4iP5WJ/j1N34L8RWnRgn/x6ZCQ1N5qgjFtEkJObu1N9fz2IcqQx8sjBzFduEv/63z/7O6jfn4jh8Bef56LLsTkTPpPBPJgrYXg9GRGCZ7A3ObVSXnuja+L19N0Y1nz/6ZJX/hu85Xol/y8zAoGBAJQw/0mEww+c2YOcNiTyPOWrJ6YYtVDoi2noESgQzfcRx2YbFjkVYK1ig+rk6oMBGQt2hTCXqv7f7HWtfJ39DZ8+nIWqMEt87O7YW1A/Lmq7nFpqqGA3W5o2w+bCaMqHypL1RZo3fwNK3dXGlWOC419oXmR0yMmpjnGH3f2MFa41"
}

]
}
14 changes: 0 additions & 14 deletions src/main/java/in/erail/common/FrameworkConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package in.erail.common;

import io.vertx.reactivex.ext.auth.oauth2.OAuth2Auth;
import io.vertx.reactivex.redis.RedisClient;
import java.util.Optional;

Expand All @@ -11,7 +10,6 @@
public class FrameworkConfiguration {

private RedisClient mRedisClient;
private OAuth2Auth mOAuth2Auth;

public RedisClient getRedisClient() {
return mRedisClient;
Expand All @@ -21,20 +19,8 @@ public void setRedisClient(RedisClient pRedisClient) {
this.mRedisClient = pRedisClient;
}

public OAuth2Auth getOAuth2Auth() {
return mOAuth2Auth;
}

public void setOAuth2Auth(OAuth2Auth pOAuth2Auth) {
this.mOAuth2Auth = pOAuth2Auth;
}


public boolean isRedisEnable(){
return Optional.ofNullable(getRedisClient()).isPresent();
}

public boolean isOAuth2AuthEnable(){
return Optional.ofNullable(getOAuth2Auth()).isPresent();
}
}
28 changes: 22 additions & 6 deletions src/main/java/in/erail/model/RequestEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.google.common.io.BaseEncoding;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.json.JsonObject;
import java.util.Map;

/**
Expand All @@ -23,9 +24,10 @@ public class RequestEvent {
private Map<String, String> mPathParameters;
private Map<String, String> mStageVariables;
@SuppressWarnings("rawtypes")
private Map mRequestContext;
private Map mRequestContext;
private byte[] mBody = new byte[0];
private boolean mIsBase64Encoded = false;
private Map<String, Object> mPrincipal;

public String getResource() {
return mResource;
Expand Down Expand Up @@ -100,12 +102,12 @@ public void setStageVariables(Map<String, String> pStageVariables) {
}

@SuppressWarnings("rawtypes")
public Map getRequestContext() {
public Map getRequestContext() {
return mRequestContext;
}

@SuppressWarnings("rawtypes")
public void setRequestContext(Map pRequestContext) {
public void setRequestContext(Map pRequestContext) {
this.mRequestContext = pRequestContext;
}

Expand All @@ -124,11 +126,25 @@ public byte[] getBody() {
public void setBody(byte[] pBody) {
this.mBody = pBody;
}
public String bodyAsString(){
if(isIsBase64Encoded()){

public String bodyAsString() {
if (isIsBase64Encoded()) {
return new String(BaseEncoding.base64().decode(new String(getBody())));
}
return new String(getBody());
}

public Map<String, Object> getPrincipal() {
return mPrincipal;
}

public void setPrincipal(Map<String, Object> pPrincipal) {
this.mPrincipal = pPrincipal;
}

@Override
public String toString() {
return JsonObject.mapFrom(this).toString();
}

}
25 changes: 16 additions & 9 deletions src/main/java/in/erail/model/ResponseEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.base.Preconditions;
import com.google.common.net.HttpHeaders;
import com.google.common.net.MediaType;
import io.vertx.core.json.JsonObject;
import io.vertx.reactivex.core.MultiMap;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -161,22 +162,28 @@ public ResponseEvent setContentType(String pContentType) {
return this;
}

public ResponseEvent setContentType(MediaType pMediaType) {
setContentType(pMediaType.toString());
return this;
}

public ResponseEvent addHeader(String pHeaderName, String pMediaType) {
mMultiValueHeaders.add(HttpHeaders.CONTENT_TYPE, pMediaType);
/**
* Predefined Content Type
* @param pMediaType
* @return Response Event
*/
public ResponseEvent setMediaType(MediaType pMediaType) {
ResponseEvent.this.setContentType(pMediaType.toString());
return this;
}

public ResponseEvent addHeader(String pHeaderName, MediaType pMediaType) {
addHeader(HttpHeaders.CONTENT_TYPE, pMediaType.toString());
public ResponseEvent addHeader(String pHeaderName, String pValue) {
mMultiValueHeaders.add(pHeaderName, pValue);
return this;
}

public String headerValue(String pHeaderName) {
return mMultiValueHeaders.get(pHeaderName);
}

@Override
public String toString() {
return JsonObject.mapFrom(this).toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,60 @@
import com.google.common.base.Strings;
import com.google.common.net.HttpHeaders;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.oauth2.impl.OAuth2AuthProviderImpl;
import io.vertx.ext.auth.oauth2.impl.OAuth2TokenImpl;
import io.vertx.reactivex.ext.auth.oauth2.AccessToken;
import io.vertx.reactivex.ext.auth.oauth2.OAuth2Auth;
import io.vertx.reactivex.ext.auth.AuthProvider;
import io.vertx.reactivex.ext.web.Router;
import io.vertx.reactivex.ext.web.RoutingContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
*
* @author vinay
*/
public class LoadUserFromAccessTokenRouteBuillder extends AbstractRouterBuilderImpl {

private OAuth2Auth mOAuth2Auth;

public OAuth2Auth getOAuth2Auth() {
return mOAuth2Auth;
}

public void setOAuth2Auth(OAuth2Auth pOAuth2Auth) {
this.mOAuth2Auth = pOAuth2Auth;
}
private final Pattern AUTH_TOKEN = Pattern.compile("^Bearer\\s(?<token>.*)");
private AuthProvider mAuthProvider;

@Override
public Router getRouter(Router pRouter) {
pRouter.route().handler(this::handle);
return pRouter;

}

public void handle(RoutingContext pRoutingContext) {

if (pRoutingContext.user() == null) {
String access_token = pRoutingContext.request().getHeader(HttpHeaders.AUTHORIZATION);
if (!Strings.isNullOrEmpty(access_token)) {
OAuth2AuthProviderImpl provider = (OAuth2AuthProviderImpl) getOAuth2Auth().getDelegate();
JsonObject accessToken = new JsonObject().put("access_token", access_token.split(" ")[1]);
try {
OAuth2TokenImpl token = new OAuth2TokenImpl(provider, accessToken);
pRoutingContext.setUser(new AccessToken(token));
} catch (RuntimeException e) {
getLog().error(e);
pRoutingContext.fail(401);
return;
Matcher tokenRegex = AUTH_TOKEN.matcher(access_token);
if (tokenRegex.find()) {
String token = tokenRegex.group("token");
JsonObject authInfo = new JsonObject()
.put("access_token", token)
.put("token_type", "Bearer")
.put("jwt", token);
try {
pRoutingContext.setUser(getAuthProvider().rxAuthenticate(authInfo).blockingGet());
} catch (RuntimeException e) {
getLog().error(e);
pRoutingContext.fail(401);
return;
}
} else {
getLog().warn(() -> "Invalid Auth Header:" + access_token);
}
}
}
pRoutingContext.next();
}

public AuthProvider getAuthProvider() {
return mAuthProvider;
}

public void setAuthProvider(AuthProvider pAuthProvider) {
this.mAuthProvider = pAuthProvider;
}

}
45 changes: 37 additions & 8 deletions src/main/java/in/erail/route/OpenAPI3RouteBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Optional;
import org.apache.commons.lang3.exception.ExceptionUtils;

/**
*
* @author vinay
*/
public class OpenAPI3RouteBuilder extends AbstractRouterBuilderImpl {

private static final String AUTHORIZATION_PREFIX = "realm";
private static final String FAIL_SUFFIX = ".fail";
private RESTService[] mServices;
private File mOpenAPI3File;
Expand Down Expand Up @@ -126,6 +126,13 @@ public JsonObject serialiseRoutingContext(RoutingContext pContext) {
request.setQueryStringParameters(convertMultiMapIntoMap(pContext.queryParams()));
request.setPathParameters(convertMultiMapIntoMap(pContext.request().params()));

JsonObject principal = Optional
.ofNullable(pContext.user())
.flatMap((t) -> Optional.ofNullable(t.principal()))
.orElse(new JsonObject());

request.setPrincipal(principal.getMap());

JsonObject result = JsonObject.mapFrom(request);

getLog().debug(() -> "Context to JSON:" + result.toString());
Expand All @@ -147,8 +154,8 @@ public HttpServerResponse buildResponseFromReply(JsonObject pReplyResponse, Rout

Optional<String> contentType = Optional.ofNullable(response.headerValue(HttpHeaders.CONTENT_TYPE));

if (contentType.isPresent()) {
response.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.OCTET_STREAM);
if (!contentType.isPresent()) {
response.setMediaType(MediaType.OCTET_STREAM);
}

response
Expand Down Expand Up @@ -183,12 +190,14 @@ public HttpServerResponse buildResponseFromReply(JsonObject pReplyResponse, Rout
.filter(t -> t.isPresent())
.forEach(t -> pContext.addCookie(t.get()));

Optional<byte[]> body = Optional.ofNullable(response.getBody());
Optional<byte[]> body = Optional
.ofNullable(response.getBody());

body.ifPresent((t) -> {
pContext.response().putHeader(HttpHeaderNames.CONTENT_LENGTH.toString(), Integer.toString(t.length));
pContext.response().write(Buffer.buffer(t));
});

return pContext.response();
}

Expand Down Expand Up @@ -222,15 +231,16 @@ public Router getRouter(Router pRouter) {
.asList(t)
.stream()
.forEach((service) -> {
getLog().debug(() -> "Adding OpenAPI service handle:" + service.getOperationId());
apiFactory.addHandlerByOperationId(service.getOperationId(), (routingContext) -> {
if (isSecurityEnable()) {
if (isSecurityEnable() && service.isSecure()) {

if (routingContext.user() == null) {
routingContext.fail(401);
return;
}

routingContext.user().isAuthorized(AUTHORIZATION_PREFIX + ":" + service.getOperationId(), (event) -> {
routingContext.user().isAuthorized(service.getAuthority(), (event) -> {
boolean authSuccess = event.succeeded() ? event.result() : false;
if (authSuccess) {
process(routingContext, service.getServiceUniqueId());
Expand All @@ -247,15 +257,34 @@ public Router getRouter(Router pRouter) {
apiFactory.addFailureHandlerByOperationId(service.getOperationId(), (routingContext) -> {
routingContext
.response()
.setStatusCode(400)
.end(routingContext.failure().toString());
.setStatusCode(routingContext.statusCode())
.end(generateErrorResponse(routingContext));
});
apiFactory.setValidationFailureHandler((routingContext) -> {
routingContext
.response()
.setStatusCode(routingContext.statusCode())
.end(generateErrorResponse(routingContext));
});
apiFactory.setNotImplementedFailureHandler((routingContext) -> {
routingContext
.response()
.setStatusCode(routingContext.statusCode())
.end(generateErrorResponse(routingContext));
});
});
});

return apiFactory.getRouter();
}

protected String generateErrorResponse(RoutingContext pContext) {
return Optional
.ofNullable(pContext.failure())
.map(error -> ExceptionUtils.getMessage(error))
.orElse(pContext.getBodyAsString());
}

public boolean isSecurityEnable() {
return mSecurityEnable;
}
Expand Down
Loading