From 84fda3f7c143f8dd77013b9e877adb242450b9c4 Mon Sep 17 00:00:00 2001 From: Sattvik Chakravarthy Date: Mon, 9 Sep 2024 18:19:05 +0530 Subject: [PATCH] fix: refactor --- src/main/java/io/supertokens/oauth/OAuth.java | 9 +- .../CreateUpdateOrGetOAuthClientAPI.java | 211 +++++----- .../OAuthAcceptAuthConsentRequestAPI.java | 52 ++- .../oauth/OAuthAcceptAuthLoginRequestAPI.java | 54 ++- .../OAuthAcceptAuthLogoutRequestAPI.java | 54 ++- .../webserver/api/oauth/OAuthAuthAPI.java | 113 +++--- .../api/oauth/OAuthClientListAPI.java | 76 ++-- .../oauth/OAuthGetAuthConsentRequestAPI.java | 52 +-- .../oauth/OAuthGetAuthLoginRequestAPI.java | 52 +-- .../oauth/OAuthGetAuthLogoutRequestAPI.java | 52 +-- .../webserver/api/oauth/OAuthProxyBase.java | 359 ------------------ .../webserver/api/oauth/OAuthProxyHelper.java | 284 ++++++++++++++ .../OAuthRejectAuthConsentRequestAPI.java | 52 ++- .../oauth/OAuthRejectAuthLoginRequestAPI.java | 52 ++- .../OAuthRejectAuthLogoutRequestAPI.java | 51 ++- .../webserver/api/oauth/OAuthTokenAPI.java | 90 ++--- .../api/oauth/RemoveOAuthClientAPI.java | 68 ++-- 17 files changed, 856 insertions(+), 825 deletions(-) delete mode 100644 src/main/java/io/supertokens/webserver/api/oauth/OAuthProxyBase.java create mode 100644 src/main/java/io/supertokens/webserver/api/oauth/OAuthProxyHelper.java diff --git a/src/main/java/io/supertokens/oauth/OAuth.java b/src/main/java/io/supertokens/oauth/OAuth.java index 4636bf15b..11ec6fa85 100644 --- a/src/main/java/io/supertokens/oauth/OAuth.java +++ b/src/main/java/io/supertokens/oauth/OAuth.java @@ -117,8 +117,13 @@ public static HttpRequest.Response handleOAuthProxyFormPOST(Main main, AppIdenti formFields = Transformations.transformFormFieldsForHydra(formFields); headers = Transformations.transformRequestHeadersForHydra(headers); - String publicOAuthProviderServiceUrl = Config.getConfig(appIdentifier.getAsPublicTenantIdentifier(), main).getOAuthProviderPublicServiceUrl(); - String fullUrl = publicOAuthProviderServiceUrl + path; + String baseURL; + if (proxyToAdmin) { + baseURL = Config.getConfig(appIdentifier.getAsPublicTenantIdentifier(), main).getOAuthProviderAdminServiceUrl(); + } else { + baseURL = Config.getConfig(appIdentifier.getAsPublicTenantIdentifier(), main).getOAuthProviderPublicServiceUrl(); + } + String fullUrl = baseURL + path; HttpRequest.Response response = HttpRequest.doFormPost(fullUrl, headers, formFields); diff --git a/src/main/java/io/supertokens/webserver/api/oauth/CreateUpdateOrGetOAuthClientAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/CreateUpdateOrGetOAuthClientAPI.java index 1dc3ea794..174a3e927 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/CreateUpdateOrGetOAuthClientAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/CreateUpdateOrGetOAuthClientAPI.java @@ -20,7 +20,6 @@ import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; -import java.util.List; import java.util.Map; import com.google.gson.JsonElement; @@ -33,146 +32,160 @@ import io.supertokens.oauth.OAuth; import io.supertokens.oauth.exceptions.OAuthAPIException; import io.supertokens.oauth.exceptions.OAuthClientNotFoundException; +import io.supertokens.pluginInterface.RECIPE_ID; import io.supertokens.pluginInterface.exceptions.InvalidConfigException; import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.pluginInterface.oauth.exceptions.OAuth2ClientAlreadyExistsForAppException; import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class CreateUpdateOrGetOAuthClientAPI extends OAuthProxyBase { +public class CreateUpdateOrGetOAuthClientAPI extends WebserverAPI { @Override public String getPath() { return "/recipe/oauth/clients"; } public CreateUpdateOrGetOAuthClientAPI(Main main){ - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) throws ServletException { - String clientId = ""; - - if (req.getMethod().equals("GET")) { - clientId = InputParser.getQueryParamOrThrowError(req, "clientId", false); - } else if (req.getMethod().equals("PUT")) { - clientId = InputParser.parseStringOrThrowError(input, "clientId", false); - } - - return new ProxyProps[] { - new ProxyProps( - "GET", // apiMethod - "GET", // method - "/admin/clients/" + clientId, // path - true, // proxyToAdmin - true // camelToSnakeCaseConversion - ), - new ProxyProps( - "POST", // apiMethod - "POST_JSON", // method - "/admin/clients", // path - true, // proxyToAdmin - true // camelToSnakeCaseConversion - ), - new ProxyProps( - "PUT", // apiMethod - "PUT_JSON", // method - "/admin/clients/" + clientId, // path + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + String clientId = InputParser.getQueryParamOrThrowError(req, "clientId", false); + + try { + OAuthProxyHelper.proxyGET( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/clients/" + clientId, // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected Map getQueryParamsForProxy(HttpServletRequest req, JsonObject input) throws IOException, ServletException { - Map queryParams = new HashMap<>(); - - String queryString = req.getQueryString(); - if (queryString != null) { - String[] queryParamsParts = queryString.split("&"); - for (String queryParam : queryParamsParts) { - String[] keyValue = queryParam.split("="); - if (keyValue.length == 2) { - queryParams.put(keyValue[0], URLDecoder.decode(keyValue[1], StandardCharsets.UTF_8)); + true, // camelToSnakeCaseConversion + () -> { // getQueryParamsForProxy + Map queryParams = new HashMap<>(); + + String queryString = req.getQueryString(); + if (queryString != null) { + String[] queryParamsParts = queryString.split("&"); + for (String queryParam : queryParamsParts) { + String[] keyValue = queryParam.split("="); + if (keyValue.length == 2) { + queryParams.put(keyValue[0], URLDecoder.decode(keyValue[1], StandardCharsets.UTF_8)); + } + } + } + + return queryParams; + }, + () -> { // getHeadersForProxy + return new HashMap<>(); + }, + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + this.sendJsonResponse(200, jsonBody, resp); } - } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); } - - return queryParams; } @Override - protected JsonObject getJsonBodyForProxyPOST(HttpServletRequest req, JsonObject input) - throws IOException, ServletException { + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); // Defaults that we require input.addProperty("accessTokenStrategy", "jwt"); input.addProperty("skipConsent", true); input.addProperty("subjectType", "public"); - return input; - } - - @Override - protected JsonObject getJsonBodyForProxyPUT(HttpServletRequest req, JsonObject input) - throws IOException, ServletException { - // fetch existing config and the apply input on top of it - String clientId = input.get("clientId").getAsString(); - try { - Map queryParams = new HashMap<>(); - queryParams.put("client_id", clientId); - HttpRequest.Response response = OAuth.handleOAuthProxyGET( - main, + OAuthProxyHelper.proxyJsonPOST( + main, req, resp, getAppIdentifier(req), enforcePublicTenantAndGetPublicTenantStorage(req), - "/admin/clients/" + clientId, - true, queryParams, null); - - JsonObject existingConfig = response.jsonResponse.getAsJsonObject(); - existingConfig = OAuth.convertSnakeCaseToCamelCaseRecursively(existingConfig).getAsJsonObject(); - for (Map.Entry entry : existingConfig.entrySet()) { - String key = entry.getKey(); - if (!input.has(key)) { - input.add(key, entry.getValue()); + "/admin/clients", // proxyPath + true, // proxyToAdmin + true, // camelToSnakeCaseConversion + () -> { // getJsonBody + return input; + }, + () -> { // getHeadersForProxy + return new HashMap<>(); + }, + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + String clientId = jsonBody.getAsJsonObject().get("clientId").getAsString(); + + try { + OAuth.addClientId(main, getAppIdentifier(req), enforcePublicTenantAndGetPublicTenantStorage(req), clientId); + } catch (StorageQueryException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } catch (OAuth2ClientAlreadyExistsForAppException e) { + // ignore + } + this.sendJsonResponse(200, jsonBody, resp); } - } - } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException | BadPermissionException e) { + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { throw new ServletException(e); - } catch (OAuthClientNotFoundException | OAuthAPIException e) { - // ignore since the PUT API will throw one of this error later on } - - return input; - } - - @Override - protected void handleResponseFromProxyGET(HttpServletRequest req, HttpServletResponse resp, int statusCode, - Map> headers, String rawBody, JsonElement jsonBody) - throws IOException, ServletException { - this.sendJsonResponse(200, jsonBody, resp); } @Override - protected void handleResponseFromProxyPOST(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - String clientId = jsonBody.getAsJsonObject().get("clientId").getAsString(); + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); + String clientId = InputParser.parseStringOrThrowError(input, "clientId", false); try { - OAuth.addClientId(main, getAppIdentifier(req), enforcePublicTenantAndGetPublicTenantStorage(req), clientId); - } catch (StorageQueryException | TenantOrAppNotFoundException | BadPermissionException e) { + OAuthProxyHelper.proxyJsonPUT( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/clients/" + clientId, + true, // proxyToAdmin + true, // camelToSnakeCaseConversion + () -> { // getJsonBody + return new HashMap<>(); + }, + () -> { // getHeadersForProxy + try { + Map queryParams = new HashMap<>(); + queryParams.put("client_id", clientId); + HttpRequest.Response response = OAuth.handleOAuthProxyGET( + main, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/clients/" + clientId, + true, queryParams, null); + + JsonObject existingConfig = response.jsonResponse.getAsJsonObject(); + existingConfig = OAuth.convertSnakeCaseToCamelCaseRecursively(existingConfig).getAsJsonObject(); + for (Map.Entry entry : existingConfig.entrySet()) { + String key = entry.getKey(); + if (!input.has(key)) { + input.add(key, entry.getValue()); + } + } + } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException | BadPermissionException e) { + throw new ServletException(e); + } catch (OAuthClientNotFoundException | OAuthAPIException e) { + // ignore since the PUT API will throw one of this error later on + } + + return input; + }, + () -> { // getHeadersForProxy + return new HashMap<>(); + }, + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + this.sendJsonResponse(200, jsonBody, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { throw new ServletException(e); - } catch (OAuth2ClientAlreadyExistsForAppException e) { - // ignore } - this.sendJsonResponse(200, jsonBody, resp); - } - - @Override - protected void handleResponseFromProxyPUT(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - this.sendJsonResponse(200, jsonBody, resp); } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthConsentRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthConsentRequestAPI.java index 194a2542f..17cdb45c1 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthConsentRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthConsentRequestAPI.java @@ -1,21 +1,27 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthAcceptAuthConsentRequestAPI extends OAuthProxyBase { +public class OAuthAcceptAuthConsentRequestAPI extends WebserverAPI { public OAuthAcceptAuthConsentRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,22 +30,28 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "PUT", // apiMethod - "PUT_JSON", // method - "/admin/oauth2/auth/requests/consent/accept", // path + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); + + try { + OAuthProxyHelper.proxyJsonPUT( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/consent/accept", // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyPUT(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + true, // camelToSnakeCaseConversion + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + () -> input, // getJsonBody + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthLoginRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthLoginRequestAPI.java index 449e09da9..ac76dd2f0 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthLoginRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthLoginRequestAPI.java @@ -1,21 +1,27 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.webserver.WebserverAPI; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.InputParser; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthAcceptAuthLoginRequestAPI extends OAuthProxyBase { +public class OAuthAcceptAuthLoginRequestAPI extends WebserverAPI { public OAuthAcceptAuthLoginRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,22 +30,28 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "PUT", // apiMethod - "PUT_JSON", // method - "/admin/oauth2/auth/requests/login/accept", // path - true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyPUT(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); + + try { + OAuthProxyHelper.proxyJsonPUT( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/login/accept", + true, + true, + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + () -> input, + HashMap::new, + (statusCode, headers, rawBody, jsonBody) -> { + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthLogoutRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthLogoutRequestAPI.java index 1533cb4d0..ec6586d2d 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthLogoutRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthAcceptAuthLogoutRequestAPI.java @@ -1,21 +1,27 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthAcceptAuthLogoutRequestAPI extends OAuthProxyBase { +public class OAuthAcceptAuthLogoutRequestAPI extends WebserverAPI { public OAuthAcceptAuthLogoutRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,22 +30,28 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "PUT", // apiMethod - "PUT_JSON", // method - "/admin/oauth2/auth/requests/logout/accept", // path - true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyPUT(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); + + try { + OAuthProxyHelper.proxyJsonPUT( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/logout/accept", + true, + true, + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + () -> input, + HashMap::new, + (statusCode, headers, rawBody, jsonBody) -> { + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthAuthAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthAuthAPI.java index ba78e910e..1e103700f 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthAuthAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthAuthAPI.java @@ -17,12 +17,15 @@ package io.supertokens.webserver.api.oauth; import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -33,9 +36,9 @@ import java.util.Map; import java.util.stream.Collectors; -public class OAuthAuthAPI extends OAuthProxyBase { +public class OAuthAuthAPI extends WebserverAPI { public OAuthAuthAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -44,62 +47,60 @@ public String getPath() { } @Override - public OAuthProxyBase.ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new OAuthProxyBase.ProxyProps[] { - new OAuthProxyBase.ProxyProps( - "POST", // apiMethod - "GET", // method - "/oauth2/auth", // path - false, // proxyToAdmin - false // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected Map getQueryParamsForProxy(HttpServletRequest req, JsonObject input) throws IOException, ServletException { + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); JsonObject params = InputParser.parseJsonObjectOrThrowError(input, "params", false); - - return params.entrySet().stream().collect(Collectors.toMap( - Map.Entry::getKey, - e -> e.getValue().getAsString() - )); - } - - @Override - protected Map getHeadersForProxy(HttpServletRequest req, JsonObject input) throws ServletException, IOException { String cookies = InputParser.parseStringOrThrowError(input, "cookies", true); - Map headers = new HashMap<>(); - - if (cookies != null) { - headers.put("Cookie", cookies); - } - - return headers; - } - - @Override - protected void handleResponseFromProxyGET(HttpServletRequest req, HttpServletResponse resp, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - if (headers == null || !headers.containsKey("Location")) { - throw new IllegalStateException("Invalid response from hydra"); + try { + OAuthProxyHelper.proxyGET( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/oauth2/auth", + false, + false, + () -> { + return params.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, + e -> e.getValue().getAsString() + )); + }, + () -> { + Map headers = new HashMap<>(); + + if (cookies != null) { + headers.put("Cookie", cookies); + } + + return headers; + }, + (statusCode, headers, rawBody, jsonBody) -> { + if (headers == null || !headers.containsKey("Location")) { + throw new IllegalStateException("Invalid response from hydra"); + } + + String redirectTo = headers.get("Location").get(0); + List responseCookies = headers.get("Set-Cookie"); + + JsonObject response = new JsonObject(); + response.addProperty("redirectTo", redirectTo); + + JsonArray jsonCookies = new JsonArray(); + if (responseCookies != null) { + for (String cookie : responseCookies) { + jsonCookies.add(new JsonPrimitive(cookie)); + } + } + + response.add("cookies", jsonCookies); + response.addProperty("status", "OK"); + super.sendJsonResponse(200, response, resp); + } + ); + + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); } - - String redirectTo = headers.get("Location").get(0); - List cookies = headers.get("Set-Cookie"); - - JsonObject response = new JsonObject(); - response.addProperty("redirectTo", redirectTo); - - JsonArray jsonCookies = new JsonArray(); - if (cookies != null) { - for (String cookie : cookies) { - jsonCookies.add(new JsonPrimitive(cookie)); - } - } - - response.add("cookies", jsonCookies); - response.addProperty("status", "OK"); - super.sendJsonResponse(200, response, resp); } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthClientListAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthClientListAPI.java index 7a9988e57..9fbdd8085 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthClientListAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthClientListAPI.java @@ -1,9 +1,9 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; +import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import com.google.gson.JsonArray; @@ -13,16 +13,18 @@ import io.supertokens.Main; import io.supertokens.multitenancy.exception.BadPermissionException; import io.supertokens.oauth.OAuth; +import io.supertokens.pluginInterface.RECIPE_ID; import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthClientListAPI extends OAuthProxyBase { +public class OAuthClientListAPI extends WebserverAPI { public OAuthClientListAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -31,45 +33,45 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "GET", // apiMethod - "GET", // method - "/admin/clients", // path + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + try { + OAuthProxyHelper.proxyGET( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/clients", // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } + true, // camelToSnakeCaseConversion + HashMap::new, // getQueryParamsForProxy + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + JsonObject response = new JsonObject(); + response.addProperty("status", "OK"); - @Override - protected void handleResponseFromProxyGET(HttpServletRequest req, HttpServletResponse resp, int statusCode, - Map> headers, String rawBody, JsonElement jsonBody) - throws IOException, ServletException { + // Filter out the clients for app + List clientIds; + try { + clientIds = OAuth.listClientIds(main, getAppIdentifier(req), enforcePublicTenantAndGetPublicTenantStorage(req)); + } catch (StorageQueryException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } - JsonObject response = new JsonObject(); - response.addProperty("status", "OK"); + Set clientIdsSet = new HashSet<>(clientIds); - // Filter out the clients for app - List clientIds; - try { - clientIds = OAuth.listClientIds(main, getAppIdentifier(req), enforcePublicTenantAndGetPublicTenantStorage(req)); - } catch (StorageQueryException | TenantOrAppNotFoundException | BadPermissionException e) { - throw new ServletException(e); - } + JsonArray clients = new JsonArray(); + + for (JsonElement clientElem : jsonBody.getAsJsonArray()) { + if (clientIdsSet.contains(clientElem.getAsJsonObject().get("clientId").getAsString())) { + clients.add(clientElem); + } + } - Set clientIdsSet = new HashSet<>(clientIds); - - JsonArray clients = new JsonArray(); - - for (JsonElement clientElem : jsonBody.getAsJsonArray()) { - if (clientIdsSet.contains(clientElem.getAsJsonObject().get("clientId").getAsString())) { - clients.add(clientElem); - } + response.add("clients", clients); + sendJsonResponse(200, response, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); } - - response.add("clients", clients); - sendJsonResponse(200, response, resp); } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthConsentRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthConsentRequestAPI.java index 624580ad6..371a0f0b1 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthConsentRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthConsentRequestAPI.java @@ -1,21 +1,26 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthGetAuthConsentRequestAPI extends OAuthProxyBase { +public class OAuthGetAuthConsentRequestAPI extends WebserverAPI { public OAuthGetAuthConsentRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,25 +29,26 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "GET", // apiMethod - "GET", // method - "/admin/oauth2/auth/requests/consent", // path + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + try { + OAuthProxyHelper.proxyGET( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/consent", // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyGET(HttpServletRequest req, HttpServletResponse resp, int statusCode, - Map> headers, String rawBody, JsonElement jsonBody) - throws IOException, ServletException { - - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + true, // camelToSnakeCaseConversion + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthLoginRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthLoginRequestAPI.java index 586e74aad..0c848d7ca 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthLoginRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthLoginRequestAPI.java @@ -1,21 +1,26 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthGetAuthLoginRequestAPI extends OAuthProxyBase { +public class OAuthGetAuthLoginRequestAPI extends WebserverAPI { public OAuthGetAuthLoginRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,25 +29,26 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "GET", // apiMethod - "GET", // method - "/admin/oauth2/auth/requests/login", // path + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + try { + OAuthProxyHelper.proxyGET( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/login", // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyGET(HttpServletRequest req, HttpServletResponse resp, int statusCode, - Map> headers, String rawBody, JsonElement jsonBody) - throws IOException, ServletException { - - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + true, // camelToSnakeCaseConversion + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthLogoutRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthLogoutRequestAPI.java index 90195c61f..3afa294d7 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthLogoutRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthGetAuthLogoutRequestAPI.java @@ -1,21 +1,26 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthGetAuthLogoutRequestAPI extends OAuthProxyBase { +public class OAuthGetAuthLogoutRequestAPI extends WebserverAPI { public OAuthGetAuthLogoutRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,25 +29,26 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "GET", // apiMethod - "GET", // method - "/admin/oauth2/auth/requests/logout", // path + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + try { + OAuthProxyHelper.proxyGET( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/logout", // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyGET(HttpServletRequest req, HttpServletResponse resp, int statusCode, - Map> headers, String rawBody, JsonElement jsonBody) - throws IOException, ServletException { - - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + true, // camelToSnakeCaseConversion + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthProxyBase.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthProxyBase.java deleted file mode 100644 index 41b8ccddc..000000000 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthProxyBase.java +++ /dev/null @@ -1,359 +0,0 @@ -package io.supertokens.webserver.api.oauth; - -import java.io.IOException; -import java.io.Serial; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; - -import io.supertokens.Main; -import io.supertokens.featureflag.exceptions.FeatureNotEnabledException; -import io.supertokens.multitenancy.exception.BadPermissionException; -import io.supertokens.oauth.HttpRequest; -import io.supertokens.oauth.OAuth; -import io.supertokens.oauth.exceptions.OAuthAPIException; -import io.supertokens.oauth.exceptions.OAuthClientNotFoundException; -import io.supertokens.pluginInterface.RECIPE_ID; -import io.supertokens.pluginInterface.Storage; -import io.supertokens.pluginInterface.exceptions.InvalidConfigException; -import io.supertokens.pluginInterface.exceptions.StorageQueryException; -import io.supertokens.pluginInterface.multitenancy.AppIdentifier; -import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; -import io.supertokens.webserver.InputParser; -import io.supertokens.webserver.WebserverAPI; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -public abstract class OAuthProxyBase extends WebserverAPI { - @Serial - private static final long serialVersionUID = -8734479943734920904L; - - public OAuthProxyBase(Main main) { - super(main, RECIPE_ID.OAUTH.toString()); - } - - public abstract ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) throws ServletException; - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { - ProxyProps[] proxyPropsList = getProxyProperties(req, null); - ProxyProps proxyProps = null; - - for (ProxyProps props : proxyPropsList) { - if (props.apiMethod.equals(req.getMethod())) { - proxyProps = props; - break; - } - } - - if (proxyProps == null) { - this.sendTextResponse(405, "Method not supported", resp); - return; - } - - if (proxyProps.method.equals("GET")) { - doProxyGetRequest(req, resp, proxyProps, null); - } else { - this.sendTextResponse(405, "Method not supported", resp); - } - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { - JsonObject input = InputParser.parseJsonObjectOrThrowError(req); - - ProxyProps[] proxyPropsList = getProxyProperties(req, input); - ProxyProps proxyProps = null; - - for (ProxyProps props : proxyPropsList) { - if (props.apiMethod.equals(req.getMethod())) { - proxyProps = props; - break; - } - } - - if (proxyProps == null) { - this.sendTextResponse(405, "Method not supported", resp); - return; - } - - if (proxyProps.method.equals("GET")) { - doProxyGetRequest(req, resp, proxyProps, input); - } else if (proxyProps.method.equals("POST_FORM")) { - doProxyPostFormRequest(req, resp, proxyProps, input); - } else if (proxyProps.method.equals("POST_JSON")) { - doProxyPostJsonRequest(req, resp, proxyProps, input); - } else if (proxyProps.method.equals("DELETE_JSON")) { - doProxyDeleteJsonRequest(req, resp, proxyProps, input); - } - } - - @Override - protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { - JsonObject input = InputParser.parseJsonObjectOrThrowError(req); - - ProxyProps[] proxyPropsList = getProxyProperties(req, input); - ProxyProps proxyProps = null; - - for (ProxyProps props : proxyPropsList) { - if (props.apiMethod.equals(req.getMethod())) { - proxyProps = props; - break; - } - } - - if (proxyProps == null) { - this.sendTextResponse(405, "Method not supported", resp); - return; - } - - if (proxyProps.method.equals("PUT_JSON")) { - doProxyPutJsonRequest(req, resp, proxyProps, input); - } else { - this.sendTextResponse(405, "Method not supported", resp); - } - } - - private void doProxyGetRequest(HttpServletRequest req, HttpServletResponse resp, ProxyProps proxyProps, JsonObject input) - throws IOException, ServletException { - Map queryParams = getQueryParamsForProxy(req, input); - - if (proxyProps.camelToSnakeCaseConversion) { - queryParams = OAuth.convertCamelToSnakeCase(queryParams); - } - - Map headers = getHeadersForProxy(req, input); - - try { - AppIdentifier appIdentifier = getAppIdentifier(req); - Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req); - HttpRequest.Response response = OAuth.handleOAuthProxyGET(main, appIdentifier, storage, proxyProps.path, proxyProps.proxyToAdmin, queryParams, headers); - - if (proxyProps.camelToSnakeCaseConversion) { - response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); - } - - handleResponseFromProxyGET(req, resp, response.statusCode, response.headers, response.rawResponse, response.jsonResponse); - - } catch (OAuthClientNotFoundException e) { - handleOAuthClientNotFoundException(resp); - } catch (OAuthAPIException e) { - handleOAuthAPIException(resp, e); - } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException | BadPermissionException e) { - throw new ServletException(e); - } - } - - private void doProxyPostFormRequest(HttpServletRequest req, HttpServletResponse resp, ProxyProps proxyProps, JsonObject input) - throws IOException, ServletException { - Map formFields = getFormFieldsForProxyPOST(req, input); - - if (proxyProps.camelToSnakeCaseConversion) { - formFields = OAuth.convertCamelToSnakeCase(formFields); - } - - Map headers = getHeadersForProxy(req, input); - - try { - AppIdentifier appIdentifier = getAppIdentifier(req); - Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req); - HttpRequest.Response response = OAuth.handleOAuthProxyFormPOST(main, appIdentifier, storage, proxyProps.path, proxyProps.proxyToAdmin, formFields, headers); - - if (proxyProps.camelToSnakeCaseConversion) { - response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); - } - - handleResponseFromProxyPOST(req, resp, input, response.statusCode, response.headers, response.rawResponse, response.jsonResponse); - - } catch (OAuthClientNotFoundException e) { - handleOAuthClientNotFoundException(resp); - } catch (OAuthAPIException e) { - handleOAuthAPIException(resp, e); - } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException | BadPermissionException e) { - throw new ServletException(e); - } - } - - private void doProxyPostJsonRequest(HttpServletRequest req, HttpServletResponse resp, ProxyProps proxyProps, JsonObject input) - throws IOException, ServletException { - JsonObject jsonInput = getJsonBodyForProxyPOST(req, input); - - if (proxyProps.camelToSnakeCaseConversion) { - jsonInput = OAuth.convertCamelToSnakeCase(jsonInput); - } - - Map headers = getHeadersForProxy(req, input); - - try { - AppIdentifier appIdentifier = getAppIdentifier(req); - Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req); - HttpRequest.Response response = OAuth.handleOAuthProxyJsonPOST(main, appIdentifier, storage, proxyProps.path, proxyProps.proxyToAdmin, jsonInput, headers); - - if (proxyProps.camelToSnakeCaseConversion) { - response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); - } - - handleResponseFromProxyPOST(req, resp, input, response.statusCode, response.headers, response.rawResponse, response.jsonResponse); - - } catch (OAuthClientNotFoundException e) { - handleOAuthClientNotFoundException(resp); - } catch (OAuthAPIException e) { - handleOAuthAPIException(resp, e); - } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException | BadPermissionException e) { - throw new ServletException(e); - } - } - - private void doProxyDeleteJsonRequest(HttpServletRequest req, HttpServletResponse resp, ProxyProps proxyProps, JsonObject input) - throws IOException, ServletException { - JsonObject jsonInput = getJsonBodyForProxyDELETE(req, input); - - if (proxyProps.camelToSnakeCaseConversion) { - jsonInput = OAuth.convertCamelToSnakeCase(jsonInput); - } - - Map headers = getHeadersForProxy(req, input); - - try { - AppIdentifier appIdentifier = getAppIdentifier(req); - Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req); - HttpRequest.Response response = OAuth.handleOAuthProxyJsonDELETE(main, appIdentifier, storage, proxyProps.path, proxyProps.proxyToAdmin, jsonInput, headers); - - if (proxyProps.camelToSnakeCaseConversion) { - response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); - } - - handleResponseFromProxyDELETE(req, resp, input, response.statusCode, response.headers, response.rawResponse, response.jsonResponse); - - } catch (OAuthClientNotFoundException e) { - handleOAuthClientNotFoundException(resp); - } catch (OAuthAPIException e) { - handleOAuthAPIException(resp, e); - } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException | BadPermissionException e) { - throw new ServletException(e); - } - } - - private void doProxyPutJsonRequest(HttpServletRequest req, HttpServletResponse resp, ProxyProps proxyProps, JsonObject input) - throws IOException, ServletException { - Map queryParams = getQueryParamsForProxy(req, input); - - if (proxyProps.camelToSnakeCaseConversion) { - queryParams = OAuth.convertCamelToSnakeCase(queryParams); - } - - JsonObject jsonInput = getJsonBodyForProxyPUT(req, input); - - if (proxyProps.camelToSnakeCaseConversion) { - jsonInput = OAuth.convertCamelToSnakeCase(jsonInput); - } - - Map headers = getHeadersForProxy(req, input); - - try { - AppIdentifier appIdentifier = getAppIdentifier(req); - Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req); - HttpRequest.Response response = OAuth.handleOAuthProxyJsonPUT(main, appIdentifier, storage, proxyProps.path, queryParams, proxyProps.proxyToAdmin, jsonInput, headers); - - if (proxyProps.camelToSnakeCaseConversion) { - response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); - } - - handleResponseFromProxyPUT(req, resp, input, response.statusCode, response.headers, response.rawResponse, response.jsonResponse); - - } catch (OAuthClientNotFoundException e) { - handleOAuthClientNotFoundException(resp); - } catch (OAuthAPIException e) { - handleOAuthAPIException(resp, e); - } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException | BadPermissionException e) { - throw new ServletException(e); - } - } - - private void handleOAuthClientNotFoundException(HttpServletResponse resp) throws IOException { - JsonObject response = new JsonObject(); - response.addProperty("status", "CLIENT_NOT_FOUND_ERROR"); - this.sendJsonResponse(200, response, resp); - } - - private void handleOAuthAPIException(HttpServletResponse resp, OAuthAPIException e) throws IOException { - JsonObject response = new JsonObject(); - response.addProperty("status", "OAUTH_ERROR"); - response.addProperty("error", e.error); - if (e.errorDebug != null) { - response.addProperty("errorDebug", e.errorDebug); - } - if (e.errorDescription != null) { - response.addProperty("errorDescription", e.errorDescription); - } - if (e.errorHint != null) { - response.addProperty("errorHint", e.errorHint); - } - response.addProperty("statusCode", e.statusCode); - this.sendJsonResponse(200, response, resp); - } - - protected Map getQueryParamsForProxy(HttpServletRequest req, JsonObject input) throws IOException, ServletException { - Map queryParams = new HashMap<>(); - for (Map.Entry entry : req.getParameterMap().entrySet()) { - queryParams.put(entry.getKey(), entry.getValue()[0]); - } - return queryParams; - } - - protected Map getHeadersForProxy(HttpServletRequest req, JsonObject input) throws IOException, ServletException { - return null; - } - - protected Map getFormFieldsForProxyPOST(HttpServletRequest req, JsonObject input) throws IOException, ServletException { - return null; - } - - protected JsonObject getJsonBodyForProxyPOST(HttpServletRequest req, JsonObject input) throws IOException, ServletException { - return input; - } - - protected JsonObject getJsonBodyForProxyPUT(HttpServletRequest req, JsonObject input) throws IOException, ServletException { - return input; - } - - protected JsonObject getJsonBodyForProxyDELETE(HttpServletRequest req, JsonObject input) throws IOException, ServletException { - return input; - } - - protected void handleResponseFromProxyGET(HttpServletRequest req, HttpServletResponse resp, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - throw new IllegalStateException("Not implemented"); - } - - protected void handleResponseFromProxyPOST(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - throw new IllegalStateException("Not implemented"); - } - - protected void handleResponseFromProxyPUT(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - throw new IllegalStateException("Not implemented"); - } - - protected void handleResponseFromProxyDELETE(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - throw new IllegalStateException("Not implemented"); - } - - public static class ProxyProps { - public final String apiMethod; - public final String method; - public final String path; - public final boolean proxyToAdmin; - public final boolean camelToSnakeCaseConversion; - - public ProxyProps(String apiMethod, String method, String path, boolean proxyToAdmin, boolean camelToSnakeCaseConversion) { - this.apiMethod = apiMethod; - this.method = method; - this.path = path; - this.proxyToAdmin = proxyToAdmin; - this.camelToSnakeCaseConversion = camelToSnakeCaseConversion; - } - } -} diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthProxyHelper.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthProxyHelper.java new file mode 100644 index 000000000..bc652fec3 --- /dev/null +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthProxyHelper.java @@ -0,0 +1,284 @@ +package io.supertokens.webserver.api.oauth; + +import java.io.IOException; +import java.io.Serial; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.supertokens.Main; +import io.supertokens.featureflag.exceptions.FeatureNotEnabledException; +import io.supertokens.oauth.HttpRequest; +import io.supertokens.oauth.OAuth; +import io.supertokens.oauth.exceptions.OAuthAPIException; +import io.supertokens.oauth.exceptions.OAuthClientNotFoundException; +import io.supertokens.pluginInterface.Storage; +import io.supertokens.pluginInterface.exceptions.InvalidConfigException; +import io.supertokens.pluginInterface.exceptions.StorageQueryException; +import io.supertokens.pluginInterface.multitenancy.AppIdentifier; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +public class OAuthProxyHelper { + @Serial + private static final long serialVersionUID = -8734479943734920904L; + + public static void proxyGET(Main main, HttpServletRequest req, HttpServletResponse resp, AppIdentifier appIdentifier, Storage storage, + String path, boolean proxyToAdmin, boolean camelToSnakeCaseConversion, + GetQueryParamsForProxy getQueryParamsForProxy, GetHeadersForProxy getHeadersForProxy, + HandleResponse handleResponse) throws IOException, ServletException { + Map queryParams = getQueryParamsForProxy.apply(); + + if (camelToSnakeCaseConversion) { + queryParams = OAuth.convertCamelToSnakeCase(queryParams); + } + + Map headers = getHeadersForProxy.apply(); + + try { + HttpRequest.Response response = OAuth.handleOAuthProxyGET(main, appIdentifier, storage, path, proxyToAdmin, queryParams, headers); + + if (camelToSnakeCaseConversion) { + response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); + } + + handleResponse.apply( + response.statusCode, + response.headers, + response.rawResponse, + response.jsonResponse + ); + + } catch (OAuthClientNotFoundException e) { + handleOAuthClientNotFoundException(resp); + } catch (OAuthAPIException e) { + handleOAuthAPIException(resp, e); + } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException e) { + throw new ServletException(e); + } + } + + public static void proxyFormPOST(Main main, HttpServletRequest req, HttpServletResponse resp, AppIdentifier appIdentifier, Storage storage, + String path, boolean proxyToAdmin, boolean camelToSnakeCaseConversion, + GetFormFieldsForProxy getFormFieldsForProxy, GetHeadersForProxy getHeadersForProxy, + HandleResponse handleResponse) throws IOException, ServletException { + Map formFields = getFormFieldsForProxy.apply(); + + if (camelToSnakeCaseConversion) { + formFields = OAuth.convertCamelToSnakeCase(formFields); + } + + Map headers = getHeadersForProxy.apply(); + + try { + HttpRequest.Response response = OAuth.handleOAuthProxyFormPOST(main, appIdentifier, storage, path, proxyToAdmin, formFields, headers); + + if (camelToSnakeCaseConversion) { + response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); + } + + handleResponse.apply( + response.statusCode, + response.headers, + response.rawResponse, + response.jsonResponse + ); + + } catch (OAuthClientNotFoundException e) { + handleOAuthClientNotFoundException(resp); + } catch (OAuthAPIException e) { + handleOAuthAPIException(resp, e); + } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException e) { + throw new ServletException(e); + } + } + + public static void proxyJsonPOST(Main main, HttpServletRequest req, HttpServletResponse resp, AppIdentifier appIdentifier, Storage storage, + String path, boolean proxyToAdmin, boolean camelToSnakeCaseConversion, + GetJsonBody getJsonBody, GetHeadersForProxy getHeadersForProxy, + HandleResponse handleResponse) throws IOException, ServletException { + JsonObject jsonInput = getJsonBody.apply(); + + if (camelToSnakeCaseConversion) { + jsonInput = OAuth.convertCamelToSnakeCase(jsonInput); + } + + Map headers = getHeadersForProxy.apply(); + + try { + HttpRequest.Response response = OAuth.handleOAuthProxyJsonPOST(main, appIdentifier, storage, path, proxyToAdmin, jsonInput, headers); + + if (camelToSnakeCaseConversion) { + response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); + } + + handleResponse.apply( + response.statusCode, + response.headers, + response.rawResponse, + response.jsonResponse + ); + + } catch (OAuthClientNotFoundException e) { + handleOAuthClientNotFoundException(resp); + } catch (OAuthAPIException e) { + handleOAuthAPIException(resp, e); + } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException e) { + throw new ServletException(e); + } + } + + public static void proxyJsonPUT(Main main, HttpServletRequest req, HttpServletResponse resp, AppIdentifier appIdentifier, Storage storage, + String path, boolean proxyToAdmin, boolean camelToSnakeCaseConversion, + GetQueryParamsForProxy getQueryParamsForProxy, GetJsonBody getJsonBodyForProxyPUT, + GetHeadersForProxy getHeadersForProxy, HandleResponse handleResponse) throws IOException, ServletException { + Map queryParams = getQueryParamsForProxy.apply(); + + if (camelToSnakeCaseConversion) { + queryParams = OAuth.convertCamelToSnakeCase(queryParams); + } + + JsonObject jsonInput = getJsonBodyForProxyPUT.apply(); + + if (camelToSnakeCaseConversion) { + jsonInput = OAuth.convertCamelToSnakeCase(jsonInput); + } + + Map headers = getHeadersForProxy.apply(); + + try { + HttpRequest.Response response = OAuth.handleOAuthProxyJsonPUT(main, appIdentifier, storage, path, queryParams, proxyToAdmin, jsonInput, headers); + + if (camelToSnakeCaseConversion) { + response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); + } + + handleResponse.apply( + response.statusCode, + response.headers, + response.rawResponse, + response.jsonResponse + ); + + } catch (OAuthClientNotFoundException e) { + handleOAuthClientNotFoundException(resp); + } catch (OAuthAPIException e) { + handleOAuthAPIException(resp, e); + } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException e) { + throw new ServletException(e); + } + } + + public static void proxyJsonDELETE(Main main, HttpServletRequest req, HttpServletResponse resp, AppIdentifier appIdentifier, Storage storage, + String path, boolean proxyToAdmin, boolean camelToSnakeCaseConversion, + GetJsonBody getJsonBodyForProxyDELETE, GetHeadersForProxy getHeadersForProxy, + HandleResponse handleResponse) throws IOException, ServletException { + JsonObject jsonInput = getJsonBodyForProxyDELETE.apply(); + + if (camelToSnakeCaseConversion) { + jsonInput = OAuth.convertCamelToSnakeCase(jsonInput); + } + + Map headers = getHeadersForProxy.apply(); + + try { + HttpRequest.Response response = OAuth.handleOAuthProxyJsonDELETE(main, appIdentifier, storage, path, proxyToAdmin, jsonInput, headers); + + if (camelToSnakeCaseConversion) { + response.jsonResponse = OAuth.convertSnakeCaseToCamelCaseRecursively(response.jsonResponse); + } + + handleResponse.apply( + response.statusCode, + response.headers, + response.rawResponse, + response.jsonResponse + ); + + } catch (OAuthClientNotFoundException e) { + handleOAuthClientNotFoundException(resp); + } catch (OAuthAPIException e) { + handleOAuthAPIException(resp, e); + } catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException | InvalidConfigException e) { + throw new ServletException(e); + } + } + + public static Map defaultGetQueryParamsFromRequest(HttpServletRequest req) { + Map queryParams = new HashMap<>(); + + String queryString = req.getQueryString(); + if (queryString != null) { + String[] queryParamsParts = queryString.split("&"); + for (String queryParam : queryParamsParts) { + String[] keyValue = queryParam.split("="); + if (keyValue.length == 2) { + queryParams.put(keyValue[0], URLDecoder.decode(keyValue[1], StandardCharsets.UTF_8)); + } + } + } + + return queryParams; + } + + @FunctionalInterface + public interface GetQueryParamsForProxy { + Map apply() throws IOException, ServletException; + } + + @FunctionalInterface + public interface GetFormFieldsForProxy { + Map apply() throws IOException, ServletException; + } + + @FunctionalInterface + public interface GetJsonBody { + JsonObject apply() throws IOException, ServletException; + } + + @FunctionalInterface + public interface GetHeadersForProxy { + Map apply() throws IOException, ServletException; + } + + @FunctionalInterface + public interface HandleResponse { + void apply(int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException; + } + + private static void handleOAuthClientNotFoundException(HttpServletResponse resp) throws IOException { + JsonObject response = new JsonObject(); + response.addProperty("status", "CLIENT_NOT_FOUND_ERROR"); + + resp.setStatus(200); + resp.setHeader("Content-Type", "application/json; charset=UTF-8"); + resp.getWriter().println(response.toString()); + } + + private static void handleOAuthAPIException(HttpServletResponse resp, OAuthAPIException e) throws IOException { + JsonObject response = new JsonObject(); + response.addProperty("status", "OAUTH_ERROR"); + response.addProperty("error", e.error); + if (e.errorDebug != null) { + response.addProperty("errorDebug", e.errorDebug); + } + if (e.errorDescription != null) { + response.addProperty("errorDescription", e.errorDescription); + } + if (e.errorHint != null) { + response.addProperty("errorHint", e.errorHint); + } + response.addProperty("statusCode", e.statusCode); + + resp.setStatus(200); + resp.setHeader("Content-Type", "application/json; charset=UTF-8"); + resp.getWriter().println(response.toString()); + } +} diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthConsentRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthConsentRequestAPI.java index 26fa0311b..ddbd04797 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthConsentRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthConsentRequestAPI.java @@ -1,21 +1,27 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthRejectAuthConsentRequestAPI extends OAuthProxyBase { +public class OAuthRejectAuthConsentRequestAPI extends WebserverAPI { public OAuthRejectAuthConsentRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,22 +30,28 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "PUT", // apiMethod - "PUT_JSON", // method - "/admin/oauth2/auth/requests/consent/reject", // path + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); + + try { + OAuthProxyHelper.proxyJsonPUT( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/consent/reject", // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyPUT(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + true, // camelToSnakeCaseConversion + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + () -> input, // getJsonBody + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthLoginRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthLoginRequestAPI.java index 78c40b8f7..4497e5395 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthLoginRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthLoginRequestAPI.java @@ -1,21 +1,25 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; -import java.util.Map; +import java.util.HashMap; + -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthRejectAuthLoginRequestAPI extends OAuthProxyBase { +public class OAuthRejectAuthLoginRequestAPI extends WebserverAPI { public OAuthRejectAuthLoginRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,22 +28,28 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "PUT", // apiMethod - "PUT_JSON", // method - "/admin/oauth2/auth/requests/login/reject", // path + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); + + try { + OAuthProxyHelper.proxyJsonPUT( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/login/reject", // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyPUT(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + true, // camelToSnakeCaseConversion + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + () -> input, // getJsonBody + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthLogoutRequestAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthLogoutRequestAPI.java index 3f89171a5..326799e03 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthLogoutRequestAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthRejectAuthLogoutRequestAPI.java @@ -1,21 +1,24 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; -import java.util.Map; +import java.util.HashMap; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class OAuthRejectAuthLogoutRequestAPI extends OAuthProxyBase { +public class OAuthRejectAuthLogoutRequestAPI extends WebserverAPI { public OAuthRejectAuthLogoutRequestAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -24,22 +27,28 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "PUT", // apiMethod - "PUT_JSON", // method - "/admin/oauth2/auth/requests/logout/reject", // path + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); + + try { + OAuthProxyHelper.proxyJsonPUT( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/oauth2/auth/requests/logout/reject", // proxyPath true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected void handleResponseFromProxyPUT(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - JsonObject response = jsonBody.getAsJsonObject(); - response.addProperty("status", "OK"); - sendJsonResponse(200, response, resp); + true, // camelToSnakeCaseConversion + () -> OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + () -> input, // getJsonBody + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + JsonObject response = jsonBody.getAsJsonObject(); + response.addProperty("status", "OK"); + sendJsonResponse(200, response, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthTokenAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthTokenAPI.java index 5e1c72bf1..d4157a95f 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/OAuthTokenAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthTokenAPI.java @@ -22,6 +22,7 @@ import io.supertokens.jwt.exceptions.UnsupportedJWTSigningAlgorithmException; import io.supertokens.multitenancy.exception.BadPermissionException; import io.supertokens.oauth.OAuth; +import io.supertokens.pluginInterface.RECIPE_ID; import io.supertokens.pluginInterface.Storage; import io.supertokens.pluginInterface.exceptions.InvalidConfigException; import io.supertokens.pluginInterface.exceptions.StorageQueryException; @@ -30,6 +31,7 @@ import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.session.jwt.JWT.JWTException; import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -42,10 +44,10 @@ import java.util.List; import java.util.Map; -public class OAuthTokenAPI extends OAuthProxyBase { +public class OAuthTokenAPI extends WebserverAPI { public OAuthTokenAPI(Main main) { - super(main); + super(main, RECIPE_ID.OAUTH.toString()); } @Override @@ -54,54 +56,54 @@ public String getPath() { } @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) { - return new ProxyProps[] { - new ProxyProps( - "POST", // apiMethod - "POST_FORM", // method - "/oauth2/token", // path - false, // proxyToAdmin - false // camelToSnakeCaseConversion - ) - }; - } - - @Override - protected Map getFormFieldsForProxyPOST(HttpServletRequest req, JsonObject input) throws IOException, ServletException { - InputParser.parseStringOrThrowError(input, "iss", false); // input validation - + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); + String iss = InputParser.parseStringOrThrowError(input, "iss", false); // input validation JsonObject bodyFromSDK = InputParser.parseJsonObjectOrThrowError(input, "body", false); - Map formFields = new HashMap<>(); - for (Map.Entry entry : bodyFromSDK.entrySet()) { - formFields.put(entry.getKey(), entry.getValue().getAsString()); - } - - return formFields; - } - - @Override - protected void handleResponseFromProxyPOST(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { - if (jsonBody == null) { - throw new IllegalStateException("unexpected response from hydra"); - } - - String iss = InputParser.parseStringOrThrowError(input, "iss", false); - boolean useDynamicKey = false; Boolean useStaticKeyInput = InputParser.parseBooleanOrThrowError(input, "useStaticSigningKey", true); - // useStaticKeyInput defaults to true, so we check if it has been explicitly set to false - useDynamicKey = Boolean.FALSE.equals(useStaticKeyInput); try { - AppIdentifier appIdentifier = getAppIdentifier(req); - Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req); - jsonBody = OAuth.transformTokens(super.main, appIdentifier, storage, jsonBody.getAsJsonObject(), iss, useDynamicKey); - - } catch (IOException | InvalidConfigException | TenantOrAppNotFoundException | BadPermissionException | StorageQueryException | InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | JWTCreationException | JWTException | StorageTransactionLogicException | UnsupportedJWTSigningAlgorithmException e) { + OAuthProxyHelper.proxyFormPOST( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/oauth2/token", // proxyPath + false, // proxyToAdmin + false, // camelToSnakeCaseConversion + () -> { + Map formFields = new HashMap<>(); + for (Map.Entry entry : bodyFromSDK.entrySet()) { + formFields.put(entry.getKey(), entry.getValue().getAsString()); + } + + return formFields; + }, + HashMap::new, + (statusCode, headers, rawBody, jsonBody) -> { + if (jsonBody == null) { + throw new IllegalStateException("unexpected response from hydra"); + } + + try { + AppIdentifier appIdentifier = getAppIdentifier(req); + Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req); + + // useStaticKeyInput defaults to true, so we check if it has been explicitly set to false + boolean useDynamicKey = false; + useDynamicKey = Boolean.FALSE.equals(useStaticKeyInput); + jsonBody = OAuth.transformTokens(super.main, appIdentifier, storage, jsonBody.getAsJsonObject(), iss, useDynamicKey); + + } catch (IOException | InvalidConfigException | TenantOrAppNotFoundException | BadPermissionException | StorageQueryException | InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | JWTCreationException | JWTException | StorageTransactionLogicException | UnsupportedJWTSigningAlgorithmException e) { + throw new ServletException(e); + } + + jsonBody.getAsJsonObject().addProperty("status", "OK"); + super.sendJsonResponse(200, jsonBody, resp); + } + ); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { throw new ServletException(e); } - - jsonBody.getAsJsonObject().addProperty("status", "OK"); - super.sendJsonResponse(200, jsonBody, resp); } } diff --git a/src/main/java/io/supertokens/webserver/api/oauth/RemoveOAuthClientAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/RemoveOAuthClientAPI.java index 06e7371ed..9692574e2 100644 --- a/src/main/java/io/supertokens/webserver/api/oauth/RemoveOAuthClientAPI.java +++ b/src/main/java/io/supertokens/webserver/api/oauth/RemoveOAuthClientAPI.java @@ -17,66 +17,64 @@ package io.supertokens.webserver.api.oauth; import java.io.IOException; -import java.util.List; -import java.util.Map; +import java.util.HashMap; + -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.supertokens.Main; import io.supertokens.multitenancy.exception.BadPermissionException; import io.supertokens.oauth.OAuth; +import io.supertokens.pluginInterface.RECIPE_ID; import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.webserver.InputParser; +import io.supertokens.webserver.WebserverAPI; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -public class RemoveOAuthClientAPI extends OAuthProxyBase { - @Override - public String getPath() { - return "/recipe/oauth/clients/remove"; - } +public class RemoveOAuthClientAPI extends WebserverAPI { public RemoveOAuthClientAPI(Main main){ - super(main); - } - - @Override - public ProxyProps[] getProxyProperties(HttpServletRequest req, JsonObject input) throws ServletException { - String clientId = InputParser.parseStringOrThrowError(input, "clientId", false); - - return new ProxyProps[] { - new ProxyProps( - "POST", // apiMethod - "DELETE_JSON", // method - "/admin/clients/" + clientId, // path - true, // proxyToAdmin - true // camelToSnakeCaseConversion - ) - }; + super(main, RECIPE_ID.OAUTH.toString()); } @Override - protected JsonObject getJsonBodyForProxyDELETE(HttpServletRequest req, JsonObject input) - throws IOException, ServletException { - - return new JsonObject(); + public String getPath() { + return "/recipe/oauth/clients/remove"; } @Override - protected void handleResponseFromProxyDELETE(HttpServletRequest req, HttpServletResponse resp, JsonObject input, int statusCode, Map> headers, String rawBody, JsonElement jsonBody) throws IOException, ServletException { + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + JsonObject input = InputParser.parseJsonObjectOrThrowError(req); String clientId = InputParser.parseStringOrThrowError(input, "clientId", false); try { - OAuth.removeClientId(main, getAppIdentifier(req), enforcePublicTenantAndGetPublicTenantStorage(req), clientId); - } catch (StorageQueryException | TenantOrAppNotFoundException | BadPermissionException e) { + OAuthProxyHelper.proxyJsonDELETE( + main, req, resp, + getAppIdentifier(req), + enforcePublicTenantAndGetPublicTenantStorage(req), + "/admin/clients/" + clientId, // proxyPath + true, // proxyToAdmin + true, // camelToSnakeCaseConversion + () -> new JsonObject(), // getJsonBody + HashMap::new, // getHeadersForProxy + (statusCode, headers, rawBody, jsonBody) -> { // handleResponse + try { + OAuth.removeClientId(main, getAppIdentifier(req), enforcePublicTenantAndGetPublicTenantStorage(req), clientId); + } catch (StorageQueryException | TenantOrAppNotFoundException | BadPermissionException e) { + throw new ServletException(e); + } + + JsonObject responseBody = new JsonObject(); + responseBody.addProperty("status", "OK"); + this.sendJsonResponse(200, responseBody, resp); + } + ); + + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException e) { throw new ServletException(e); } - - JsonObject responseBody = new JsonObject(); - responseBody.addProperty("status", "OK"); - this.sendJsonResponse(200, responseBody, resp); } }