forked from loafle/openapi-generator-original
Merge remote-tracking branch 'origin/master' into 6.0.x
This commit is contained in:
@@ -19,6 +19,7 @@ app/controllers/UserApiControllerImp.java
|
||||
app/controllers/UserApiControllerImpInterface.java
|
||||
app/openapitools/ApiCall.java
|
||||
app/openapitools/OpenAPIUtils.java
|
||||
app/openapitools/SecurityAPIUtils.java
|
||||
build.sbt
|
||||
conf/application.conf
|
||||
conf/logback.xml
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
import controllers.*;
|
||||
import openapitools.SecurityAPIUtils;
|
||||
|
||||
public class Module extends AbstractModule {
|
||||
|
||||
@@ -9,5 +10,6 @@ public class Module extends AbstractModule {
|
||||
bind(PetApiControllerImpInterface.class).to(PetApiControllerImp.class);
|
||||
bind(StoreApiControllerImpInterface.class).to(StoreApiControllerImp.class);
|
||||
bind(UserApiControllerImpInterface.class).to(UserApiControllerImp.class);
|
||||
bind(SecurityAPIUtils.class);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,9 @@ import play.mvc.Result;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import openapitools.OpenAPIUtils;
|
||||
import openapitools.SecurityAPIUtils;
|
||||
import static play.mvc.Results.ok;
|
||||
import static play.mvc.Results.unauthorized;
|
||||
import play.libs.Files.TemporaryFile;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
@@ -23,47 +25,70 @@ import javax.validation.constraints.*;
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
public abstract class PetApiControllerImpInterface {
|
||||
@Inject private Config configuration;
|
||||
@Inject private SecurityAPIUtils securityAPIUtils;
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public Result addPetHttp(Http.Request request, Pet body) {
|
||||
if (!securityAPIUtils.isRequestTokenValid(request, "petstore_auth")) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
addPet(request, body);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
public abstract void addPet(Http.Request request, Pet body) ;
|
||||
|
||||
public Result deletePetHttp(Http.Request request, Long petId, String apiKey) {
|
||||
if (!securityAPIUtils.isRequestTokenValid(request, "petstore_auth")) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
deletePet(request, petId, apiKey);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
public abstract void deletePet(Http.Request request, Long petId, String apiKey) ;
|
||||
|
||||
public Result findPetsByStatusHttp(Http.Request request, @NotNull List<String> status) {
|
||||
List<Pet> obj = findPetsByStatus(request, status);
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
for (Pet curItem : obj) {
|
||||
OpenAPIUtils.validate(curItem);
|
||||
if (!securityAPIUtils.isRequestTokenValid(request, "petstore_auth")) {
|
||||
return unauthorized();
|
||||
}
|
||||
}
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
|
||||
List<Pet> obj = findPetsByStatus(request, status);
|
||||
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
for (Pet curItem : obj) {
|
||||
OpenAPIUtils.validate(curItem);
|
||||
}
|
||||
}
|
||||
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
public abstract List<Pet> findPetsByStatus(Http.Request request, @NotNull List<String> status) ;
|
||||
|
||||
public Result findPetsByTagsHttp(Http.Request request, @NotNull List<String> tags) {
|
||||
List<Pet> obj = findPetsByTags(request, tags);
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
for (Pet curItem : obj) {
|
||||
OpenAPIUtils.validate(curItem);
|
||||
if (!securityAPIUtils.isRequestTokenValid(request, "petstore_auth")) {
|
||||
return unauthorized();
|
||||
}
|
||||
}
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
|
||||
List<Pet> obj = findPetsByTags(request, tags);
|
||||
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
for (Pet curItem : obj) {
|
||||
OpenAPIUtils.validate(curItem);
|
||||
}
|
||||
}
|
||||
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
@@ -71,39 +96,57 @@ return ok(result);
|
||||
|
||||
public Result getPetByIdHttp(Http.Request request, Long petId) {
|
||||
Pet obj = getPetById(request, petId);
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
OpenAPIUtils.validate(obj);
|
||||
}
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
}
|
||||
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
public abstract Pet getPetById(Http.Request request, Long petId) ;
|
||||
|
||||
public Result updatePetHttp(Http.Request request, Pet body) {
|
||||
if (!securityAPIUtils.isRequestTokenValid(request, "petstore_auth")) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
updatePet(request, body);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
public abstract void updatePet(Http.Request request, Pet body) ;
|
||||
|
||||
public Result updatePetWithFormHttp(Http.Request request, Long petId, String name, String status) {
|
||||
if (!securityAPIUtils.isRequestTokenValid(request, "petstore_auth")) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
updatePetWithForm(request, petId, name, status);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
public abstract void updatePetWithForm(Http.Request request, Long petId, String name, String status) ;
|
||||
|
||||
public Result uploadFileHttp(Http.Request request, Long petId, String additionalMetadata, Http.MultipartFormData.FilePart<TemporaryFile> file) {
|
||||
if (!securityAPIUtils.isRequestTokenValid(request, "petstore_auth")) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
ModelApiResponse obj = uploadFile(request, petId, additionalMetadata, file);
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
OpenAPIUtils.validate(obj);
|
||||
}
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
}
|
||||
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ import play.mvc.Result;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import openapitools.OpenAPIUtils;
|
||||
import openapitools.SecurityAPIUtils;
|
||||
import static play.mvc.Results.ok;
|
||||
import static play.mvc.Results.unauthorized;
|
||||
import play.libs.Files.TemporaryFile;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
@@ -22,11 +24,12 @@ import javax.validation.constraints.*;
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
public abstract class StoreApiControllerImpInterface {
|
||||
@Inject private Config configuration;
|
||||
@Inject private SecurityAPIUtils securityAPIUtils;
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public Result deleteOrderHttp(Http.Request request, String orderId) {
|
||||
deleteOrder(request, orderId);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
@@ -34,8 +37,9 @@ return ok();
|
||||
|
||||
public Result getInventoryHttp(Http.Request request) {
|
||||
Map<String, Integer> obj = getInventory(request);
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
@@ -43,11 +47,14 @@ return ok(result);
|
||||
|
||||
public Result getOrderByIdHttp(Http.Request request, @Min(1) @Max(5)Long orderId) {
|
||||
Order obj = getOrderById(request, orderId);
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
OpenAPIUtils.validate(obj);
|
||||
}
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
}
|
||||
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
@@ -55,11 +62,14 @@ return ok(result);
|
||||
|
||||
public Result placeOrderHttp(Http.Request request, Order body) {
|
||||
Order obj = placeOrder(request, body);
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
OpenAPIUtils.validate(obj);
|
||||
}
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
}
|
||||
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ import play.mvc.Result;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import openapitools.OpenAPIUtils;
|
||||
import openapitools.SecurityAPIUtils;
|
||||
import static play.mvc.Results.ok;
|
||||
import static play.mvc.Results.unauthorized;
|
||||
import play.libs.Files.TemporaryFile;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
@@ -23,11 +25,12 @@ import javax.validation.constraints.*;
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
public abstract class UserApiControllerImpInterface {
|
||||
@Inject private Config configuration;
|
||||
@Inject private SecurityAPIUtils securityAPIUtils;
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public Result createUserHttp(Http.Request request, User body) {
|
||||
createUser(request, body);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +38,7 @@ return ok();
|
||||
|
||||
public Result createUsersWithArrayInputHttp(Http.Request request, List<User> body) {
|
||||
createUsersWithArrayInput(request, body);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
@@ -43,7 +46,7 @@ return ok();
|
||||
|
||||
public Result createUsersWithListInputHttp(Http.Request request, List<User> body) {
|
||||
createUsersWithListInput(request, body);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
@@ -51,7 +54,7 @@ return ok();
|
||||
|
||||
public Result deleteUserHttp(Http.Request request, String username) {
|
||||
deleteUser(request, username);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
@@ -59,11 +62,14 @@ return ok();
|
||||
|
||||
public Result getUserByNameHttp(Http.Request request, String username) {
|
||||
User obj = getUserByName(request, username);
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
|
||||
if (configuration.getBoolean("useOutputBeanValidation")) {
|
||||
OpenAPIUtils.validate(obj);
|
||||
}
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
}
|
||||
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
@@ -71,8 +77,9 @@ return ok(result);
|
||||
|
||||
public Result loginUserHttp(Http.Request request, @NotNull String username, @NotNull String password) {
|
||||
String obj = loginUser(request, username, password);
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
return ok(result);
|
||||
JsonNode result = mapper.valueToTree(obj);
|
||||
|
||||
return ok(result);
|
||||
|
||||
}
|
||||
|
||||
@@ -80,7 +87,7 @@ return ok(result);
|
||||
|
||||
public Result logoutUserHttp(Http.Request request) {
|
||||
logoutUser(request);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
@@ -88,7 +95,7 @@ return ok();
|
||||
|
||||
public Result updateUserHttp(Http.Request request, String username, User body) {
|
||||
updateUser(request, username, body);
|
||||
return ok();
|
||||
return ok();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package openapitools;
|
||||
|
||||
import com.auth0.jwk.Jwk;
|
||||
import com.auth0.jwk.UrlJwkProvider;
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.typesafe.config.Config;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import play.mvc.Http;
|
||||
|
||||
import java.net.URL;
|
||||
import java.security.PublicKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
public class SecurityAPIUtils {
|
||||
private final String bearerPrefix = "Bearer ";
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
private boolean useOnlineValidation = false;
|
||||
|
||||
// Online validation
|
||||
private HashMap<String, String> tokenIntrospectEndpoints = new HashMap<>();
|
||||
private final String clientId;
|
||||
private final String clientSecret;
|
||||
|
||||
// Offline validation
|
||||
private HashMap<String, String> jwksEndpoints = new HashMap<>();
|
||||
private String tokenKeyId = "";
|
||||
private JWTVerifier tokenVerifier; //Reusable verifier instance until tokenKeyId changes.
|
||||
|
||||
@Inject
|
||||
SecurityAPIUtils(Config configuration) {
|
||||
mapper = new ObjectMapper();
|
||||
|
||||
clientId = configuration.hasPath("oauth.clientId") ? configuration.getString("oauth.clientId") : "";
|
||||
clientSecret = configuration.hasPath("oauth.clientSecret") ? configuration.getString("oauth.clientSecret") : "";
|
||||
|
||||
tokenIntrospectEndpoints.put("petstore_auth", "");
|
||||
|
||||
jwksEndpoints.put("petstore_auth", "");
|
||||
}
|
||||
|
||||
private boolean isRequestTokenValidByOnlineCheck(Http.Request request, String securityMethodName) {
|
||||
try {
|
||||
Optional<String> authToken = request.getHeaders().get(HttpHeaders.AUTHORIZATION);
|
||||
|
||||
if (authToken.isPresent()) {
|
||||
String tokenWithoutBearerPrefix = authToken.get().substring(bearerPrefix.length());
|
||||
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
HttpClient httpClient = builder.build();
|
||||
HttpPost httppost = new HttpPost(this.tokenIntrospectEndpoints.get(securityMethodName));
|
||||
|
||||
List<NameValuePair> params = new ArrayList<>();
|
||||
params.add(new BasicNameValuePair("token", tokenWithoutBearerPrefix));
|
||||
params.add(new BasicNameValuePair("client_id", clientId));
|
||||
params.add(new BasicNameValuePair("client_secret", clientSecret));
|
||||
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
|
||||
|
||||
HttpResponse response = httpClient.execute(httppost);
|
||||
String responseJsonString = EntityUtils.toString(response.getEntity());
|
||||
HashMap responseJsonObject = mapper.readValue(responseJsonString, HashMap.class);
|
||||
|
||||
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK && (boolean) responseJsonObject.get("active");
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isRequestTokenValidByOfflineCheck(Http.Request request, String securityMethodName) {
|
||||
try {
|
||||
Optional<String> authHeader = request.getHeaders().get(HttpHeaders.AUTHORIZATION);
|
||||
|
||||
if (authHeader.isPresent()) {
|
||||
String bearerToken = authHeader.get().substring(bearerPrefix.length());
|
||||
return isTokenValidByOfflineCheck(bearerToken, securityMethodName);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isTokenValidByOfflineCheck(String bearerToken, String securityMethodName) {
|
||||
try {
|
||||
DecodedJWT jwt = JWT.decode(bearerToken);
|
||||
String issuer = jwt.getIssuer();
|
||||
String keyId = jwt.getKeyId();
|
||||
if (!tokenKeyId.equals(keyId)) {
|
||||
if (securityMethodName == null) {
|
||||
securityMethodName = jwksEndpoints.keySet().stream().findFirst().get();
|
||||
}
|
||||
|
||||
Jwk jwk = new UrlJwkProvider(new URL(this.jwksEndpoints.get(securityMethodName))).get(keyId);
|
||||
final PublicKey publicKey = jwk.getPublicKey();
|
||||
|
||||
if (!(publicKey instanceof RSAPublicKey)) {
|
||||
throw new IllegalArgumentException(String.format("Key with ID %s was found in JWKS but is not a RSA-key.", keyId));
|
||||
}
|
||||
|
||||
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) publicKey, null);
|
||||
tokenVerifier = JWT.require(algorithm)
|
||||
.withIssuer(issuer)
|
||||
.build();
|
||||
tokenKeyId = keyId;
|
||||
}
|
||||
|
||||
DecodedJWT verifiedJWT = tokenVerifier.verify(bearerToken);
|
||||
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getOAuthUserIdFromRequestToken(Http.Request requestWithPreviouslyVerifiedToken) {
|
||||
try {
|
||||
Optional<String> authHeader = requestWithPreviouslyVerifiedToken.getHeaders().get(HttpHeaders.AUTHORIZATION);
|
||||
if (authHeader.isPresent()) {
|
||||
String bearerToken = authHeader.get().substring(bearerPrefix.length());
|
||||
return getOAuthUserIdFromToken(bearerToken);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getOAuthUserIdFromToken(String bearerToken) {
|
||||
try {
|
||||
DecodedJWT jwt = JWT.decode(bearerToken);
|
||||
return jwt.getSubject();
|
||||
} catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRequestTokenValid(Http.Request request, String securityMethodName) {
|
||||
return useOnlineValidation ? isRequestTokenValidByOnlineCheck(request, securityMethodName) : isRequestTokenValidByOfflineCheck(request, securityMethodName);
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,6 @@ scalaVersion := "2.12.6"
|
||||
libraryDependencies += "org.webjars" % "swagger-ui" % "3.32.5"
|
||||
libraryDependencies += "javax.validation" % "validation-api" % "2.0.1.Final"
|
||||
libraryDependencies += guice
|
||||
libraryDependencies += "com.auth0" % "java-jwt" % "3.18.1"
|
||||
libraryDependencies += "com.auth0" % "jwks-rsa" % "0.19.0"
|
||||
libraryDependencies += "org.apache.httpcomponents" % "httpclient" % "4.5.6"
|
||||
|
||||
Reference in New Issue
Block a user