diff --git a/src/main/java/io/supertokens/inmemorydb/Start.java b/src/main/java/io/supertokens/inmemorydb/Start.java index 19e4128d6..dcf416dbd 100644 --- a/src/main/java/io/supertokens/inmemorydb/Start.java +++ b/src/main/java/io/supertokens/inmemorydb/Start.java @@ -3011,7 +3011,7 @@ public int countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(A } @Override - public boolean doesClientIdExistForThisApp(AppIdentifier appIdentifier, String clientId) + public boolean doesClientIdExistForApp(AppIdentifier appIdentifier, String clientId) throws StorageQueryException { try { return OAuthQueries.isClientIdForAppId(this, clientId, appIdentifier); @@ -3021,7 +3021,7 @@ public boolean doesClientIdExistForThisApp(AppIdentifier appIdentifier, String c } @Override - public void addClientForApp(AppIdentifier appIdentifier, String clientId) + public void addOrUpdateClientForApp(AppIdentifier appIdentifier, String clientId, boolean isClientCredentialsOnly) throws StorageQueryException, OAuth2ClientAlreadyExistsForAppException { try { OAuthQueries.insertClientIdForAppId(this, clientId, appIdentifier); @@ -3076,4 +3076,26 @@ public boolean isRevoked(AppIdentifier appIdentifier, String[] targetTypes, Stri throw new StorageQueryException(e); } } + + @Override + public int countTotalNumberOfClientCredentialsOnlyClientsForApp(AppIdentifier appIdentifier) + throws StorageQueryException { + return 0; // TODO + } + + @Override + public int countTotalNumberOfClientsForApp(AppIdentifier appIdentifier) throws StorageQueryException { + return 0; // TODO + } + + @Override + public int countTotalNumberOfM2MTokensAlive(AppIdentifier appIdentifier) throws StorageQueryException { + return 0; // TODO + } + + @Override + public int countTotalNumberOfM2MTokensCreatedSince(AppIdentifier appIdentifier, long since) + throws StorageQueryException { + return 0; // TODO + } } diff --git a/src/main/java/io/supertokens/oauth/OAuth.java b/src/main/java/io/supertokens/oauth/OAuth.java index 9397ed6c9..5751c5216 100644 --- a/src/main/java/io/supertokens/oauth/OAuth.java +++ b/src/main/java/io/supertokens/oauth/OAuth.java @@ -74,7 +74,7 @@ public static HttpRequestForOry.Response doOAuthProxyGET(Main main, AppIdentifie } if (clientIdToCheck != null) { - if (!oauthStorage.doesClientIdExistForThisApp(appIdentifier, clientIdToCheck)) { + if (!oauthStorage.doesClientIdExistForApp(appIdentifier, clientIdToCheck)) { throw new OAuthClientNotFoundException(); } } @@ -115,7 +115,7 @@ public static HttpRequestForOry.Response doOAuthProxyFormPOST(Main main, AppIden } if (clientIdToCheck != null) { - if (!oauthStorage.doesClientIdExistForThisApp(appIdentifier, clientIdToCheck)) { + if (!oauthStorage.doesClientIdExistForApp(appIdentifier, clientIdToCheck)) { throw new OAuthClientNotFoundException(); } } @@ -156,7 +156,7 @@ public static HttpRequestForOry.Response doOAuthProxyJsonPOST(Main main, AppIden } if (clientIdToCheck != null) { - if (!oauthStorage.doesClientIdExistForThisApp(appIdentifier, clientIdToCheck)) { + if (!oauthStorage.doesClientIdExistForApp(appIdentifier, clientIdToCheck)) { throw new OAuthClientNotFoundException(); } } @@ -198,7 +198,7 @@ public static HttpRequestForOry.Response doOAuthProxyJsonPUT(Main main, AppIdent } if (clientIdToCheck != null) { - if (!oauthStorage.doesClientIdExistForThisApp(appIdentifier, clientIdToCheck)) { + if (!oauthStorage.doesClientIdExistForApp(appIdentifier, clientIdToCheck)) { throw new OAuthClientNotFoundException(); } } @@ -239,7 +239,7 @@ public static HttpRequestForOry.Response doOAuthProxyJsonDELETE(Main main, AppId } if (clientIdToCheck != null) { - if (!oauthStorage.doesClientIdExistForThisApp(appIdentifier, clientIdToCheck)) { + if (!oauthStorage.doesClientIdExistForApp(appIdentifier, clientIdToCheck)) { throw new OAuthClientNotFoundException(); } } @@ -289,6 +289,8 @@ public static JsonObject transformTokens(Main main, AppIdentifier appIdentifier, String rtHash = null; String atHash = null; + System.out.println("jsonBody: " + jsonBody.toString()); + if (jsonBody.has("refresh_token")) { String refreshToken = jsonBody.get("refresh_token").getAsString(); refreshToken = refreshToken.replace("ory_rt_", "st_rt_"); @@ -299,6 +301,7 @@ public static JsonObject transformTokens(Main main, AppIdentifier appIdentifier, if (jsonBody.has("access_token")) { String accessToken = jsonBody.get("access_token").getAsString(); + System.out.println("accessToken: " + accessToken); accessToken = OAuthToken.reSignToken(appIdentifier, main, accessToken, iss, accessTokenUpdate, rtHash, null, OAuthToken.TokenType.ACCESS_TOKEN, useDynamicKey, 0); jsonBody.addProperty("access_token", accessToken); @@ -323,9 +326,9 @@ public static JsonObject transformTokens(Main main, AppIdentifier appIdentifier, return jsonBody; } - public static void addClientId(Main main, AppIdentifier appIdentifier, Storage storage, String clientId) throws StorageQueryException, OAuth2ClientAlreadyExistsForAppException { + public static void addClientId(Main main, AppIdentifier appIdentifier, Storage storage, String clientId, boolean isClientCredentialsOnly) throws StorageQueryException, OAuth2ClientAlreadyExistsForAppException { OAuthStorage oauthStorage = StorageUtils.getOAuthStorage(storage); - oauthStorage.addClientForApp(appIdentifier, clientId); + oauthStorage.addOrUpdateClientForApp(appIdentifier, clientId, isClientCredentialsOnly); } public static void removeClientId(Main main, AppIdentifier appIdentifier, Storage storage, String clientId) throws StorageQueryException { @@ -510,4 +513,10 @@ public static void revokeSessionHandle(Main main, AppIdentifier appIdentifier, S OAuthStorage oauthStorage = StorageUtils.getOAuthStorage(storage); oauthStorage.revoke(appIdentifier, "session_handle", sessionHandle); } + + public static void verifyIdTokenAndClientIdForLogout(Main main, AppIdentifier appIdentifier, Storage storage, + String idTokenHint, String clientId) throws StorageQueryException, OAuthAPIException { + + } + } diff --git a/src/main/java/io/supertokens/webserver/Webserver.java b/src/main/java/io/supertokens/webserver/Webserver.java index db535b47f..f283ca8b2 100644 --- a/src/main/java/io/supertokens/webserver/Webserver.java +++ b/src/main/java/io/supertokens/webserver/Webserver.java @@ -288,6 +288,7 @@ private void setupRoutes() { addAPI(new RevokeOAuthTokenAPI(main)); addAPI(new RevokeOAuthTokensAPI(main)); addAPI(new RevokeOAuthSessionAPI(main)); + addAPI(new OAuthLogoutAPI(main)); StandardContext context = tomcatReference.getContext(); Tomcat tomcat = tomcatReference.getTomcat(); diff --git a/src/main/java/io/supertokens/webserver/api/oauth/OAuthLogoutAPI.java b/src/main/java/io/supertokens/webserver/api/oauth/OAuthLogoutAPI.java new file mode 100644 index 000000000..089d9381b --- /dev/null +++ b/src/main/java/io/supertokens/webserver/api/oauth/OAuthLogoutAPI.java @@ -0,0 +1,73 @@ +package io.supertokens.webserver.api.oauth; + +import java.io.IOException; +import java.util.HashMap; + +import com.google.gson.JsonObject; + +import io.supertokens.Main; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.oauth.HttpRequestForOry; +import io.supertokens.oauth.OAuth; +import io.supertokens.oauth.exceptions.OAuthAPIException; +import io.supertokens.pluginInterface.RECIPE_ID; +import io.supertokens.pluginInterface.Storage; +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 class OAuthLogoutAPI extends WebserverAPI { + public OAuthLogoutAPI(Main main){ + super(main, RECIPE_ID.OAUTH.toString()); + } + + @Override + public String getPath() { + return "/recipe/oauth/sessions/logout"; + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + String idTokenHint = InputParser.getQueryParamOrThrowError(req, "idTokenHint", true); + String clientId = InputParser.getQueryParamOrThrowError(req, "clientId", true); + + try { + AppIdentifier appIdentifier = getAppIdentifier(req); + Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req); + + OAuth.verifyIdTokenAndClientIdForLogout(main, appIdentifier, storage, idTokenHint, clientId); + + HttpRequestForOry.Response response = OAuthProxyHelper.proxyGET( + main, req, resp, + appIdentifier, + storage, + null, // clientIdToCheck + "/oauth2/sessions/logout", // proxyPath + false, // proxyToAdmin + true, // camelToSnakeCaseConversion + OAuthProxyHelper.defaultGetQueryParamsFromRequest(req), + new HashMap<>() // headers + ); + + if (response != null) { + JsonObject finalResponse = new JsonObject(); + String redirectTo = response.headers.get("Location").get(0); + + finalResponse.addProperty("status", "OK"); + finalResponse.addProperty("redirectTo", redirectTo); + + super.sendJsonResponse(200, finalResponse, resp); + } + + } catch (OAuthAPIException e) { + OAuthProxyHelper.handleOAuthAPIException(resp, e); + } catch (IOException | TenantOrAppNotFoundException | BadPermissionException | StorageQueryException e) { + throw new ServletException(e); + } + } +}