Skip to content

Commit

Permalink
fix: gid in refresh token
Browse files Browse the repository at this point in the history
  • Loading branch information
sattvikc committed Sep 24, 2024
1 parent e9770fa commit 930cd2c
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 19 deletions.
18 changes: 7 additions & 11 deletions src/main/java/io/supertokens/oauth/OAuth.java
Original file line number Diff line number Diff line change
Expand Up @@ -328,20 +328,17 @@ public static String transformTokensInAuthRedirect(Main main, AppIdentifier appI
}

public static JsonObject transformTokens(Main main, AppIdentifier appIdentifier, Storage storage, JsonObject jsonBody, String iss, JsonObject accessTokenUpdate, JsonObject idTokenUpdate, boolean useDynamicKey) throws IOException, JWTException, InvalidKeyException, NoSuchAlgorithmException, StorageQueryException, StorageTransactionLogicException, UnsupportedJWTSigningAlgorithmException, TenantOrAppNotFoundException, InvalidKeySpecException, JWTCreationException, InvalidConfigException {
String rtHash = null;
String atHash = null;

if (jsonBody.has("refresh_token")) {
String refreshToken = jsonBody.get("refresh_token").getAsString();
refreshToken = refreshToken.replace("ory_rt_", "st_rt_");
jsonBody.addProperty("refresh_token", refreshToken);

rtHash = Utils.hashSHA256(refreshToken);
}

if (jsonBody.has("access_token")) {
String accessToken = jsonBody.get("access_token").getAsString();
accessToken = OAuthToken.reSignToken(appIdentifier, main, accessToken, iss, accessTokenUpdate, rtHash, null, OAuthToken.TokenType.ACCESS_TOKEN, useDynamicKey, 0);
accessToken = OAuthToken.reSignToken(appIdentifier, main, accessToken, iss, accessTokenUpdate, null, OAuthToken.TokenType.ACCESS_TOKEN, useDynamicKey, 0);
jsonBody.addProperty("access_token", accessToken);

// Compute at_hash as per OAuth 2.0 standard
Expand All @@ -358,7 +355,7 @@ public static JsonObject transformTokens(Main main, AppIdentifier appIdentifier,

if (jsonBody.has("id_token")) {
String idToken = jsonBody.get("id_token").getAsString();
idToken = OAuthToken.reSignToken(appIdentifier, main, idToken, iss, idTokenUpdate, null, atHash, OAuthToken.TokenType.ID_TOKEN, useDynamicKey, 0);
idToken = OAuthToken.reSignToken(appIdentifier, main, idToken, iss, idTokenUpdate, atHash, OAuthToken.TokenType.ID_TOKEN, useDynamicKey, 0);
jsonBody.addProperty("id_token", idToken);
}

Expand Down Expand Up @@ -475,9 +472,9 @@ private static boolean isTokenRevokedBasedOnPayload(OAuthStorage oauthStorage, A
targetValues.add(payload.get("jti").getAsString());
}

if (payload.has("rt_hash")) {
targetTypes.add("rt_hash");
targetValues.add(payload.get("rt_hash").getAsString());
if (payload.has("gid")) {
targetTypes.add("gid");
targetValues.add(payload.get("gid").getAsString());
}

if (payload.has("sessionHandle")) {
Expand Down Expand Up @@ -522,10 +519,9 @@ public static void revokeTokensForClientId(Main main, AppIdentifier appIdentifie
oauthStorage.revoke(appIdentifier, "client_id", clientId);
}

public static void revokeRefreshToken(Main main, AppIdentifier appIdentifier, Storage storage, String token) throws StorageQueryException, NoSuchAlgorithmException {
public static void revokeRefreshToken(Main main, AppIdentifier appIdentifier, Storage storage, String gid) throws StorageQueryException, NoSuchAlgorithmException {
OAuthStorage oauthStorage = StorageUtils.getOAuthStorage(storage);
String hash = Utils.hashSHA256(token);
oauthStorage.revoke(appIdentifier, "rt_hash", hash);
oauthStorage.revoke(appIdentifier, "gid", gid);
}

public static void revokeAccessToken(Main main, AppIdentifier appIdentifier,
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/io/supertokens/oauth/OAuthToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public int getValue() {
private static Set<String> NON_OVERRIDABLE_TOKEN_PROPS = Set.of(
"kid", "typ", "alg", "aud",
"iss", "iat", "exp", "nbf", "jti", "ext",
"sid", "rat", "at_hash", "rt_hash",
"sid", "rat", "at_hash", "gid",
"client_id", "scp", "sub", "stt"
);

Expand Down Expand Up @@ -95,16 +95,12 @@ public static JsonObject getPayloadFromJWTToken(AppIdentifier appIdentifier,
return jwtInfo.payload;
}

public static String reSignToken(AppIdentifier appIdentifier, Main main, String token, String iss, JsonObject payloadUpdate, String rtHash, String atHash, TokenType tokenType, boolean useDynamicSigningKey, int retryCount) throws IOException, JWTException, InvalidKeyException, NoSuchAlgorithmException, StorageQueryException, StorageTransactionLogicException, UnsupportedJWTSigningAlgorithmException, TenantOrAppNotFoundException, InvalidKeySpecException,
public static String reSignToken(AppIdentifier appIdentifier, Main main, String token, String iss, JsonObject payloadUpdate, String atHash, TokenType tokenType, boolean useDynamicSigningKey, int retryCount) throws IOException, JWTException, InvalidKeyException, NoSuchAlgorithmException, StorageQueryException, StorageTransactionLogicException, UnsupportedJWTSigningAlgorithmException, TenantOrAppNotFoundException, InvalidKeySpecException,
JWTCreationException {
JsonObject payload = JWT.getPayloadWithoutVerifying(token).payload;

payload.addProperty("iss", iss);
payload.addProperty("stt", tokenType.getValue());
if (rtHash != null) {
payload.addProperty("rt_hash", rtHash);
}

if (atHash != null) {
payload.addProperty("at_hash", atHash);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/supertokens/oauth/Transformations.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import io.supertokens.utils.Utils;

public class Transformations {
private static Set<String> EXT_PROPS = Set.of("iss", "rsub", "tId", "sessionHandle");
private static Set<String> EXT_PROPS = Set.of("iss", "rsub", "tId", "sessionHandle", "gid");

private static Set<String> CLIENT_PROPS = Set.of(
"clientId",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import java.util.HashMap;
import java.util.UUID;

import com.google.gson.JsonObject;

Expand Down Expand Up @@ -40,6 +41,7 @@ protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws IO
accessToken.addProperty("tId", tId);
accessToken.addProperty("rsub", rsub);
accessToken.addProperty("sessionHandle", sessionHandle);
accessToken.addProperty("gid", UUID.randomUUID().toString());

// remove the above from input
input.remove("iss");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
import com.google.gson.JsonObject;

import io.supertokens.Main;
import io.supertokens.featureflag.exceptions.FeatureNotEnabledException;
import io.supertokens.jwt.exceptions.UnsupportedJWTSigningAlgorithmException;
import io.supertokens.multitenancy.exception.BadPermissionException;
import io.supertokens.oauth.HttpRequestForOry;
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;
import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException;
import io.supertokens.pluginInterface.multitenancy.AppIdentifier;
Expand Down Expand Up @@ -44,6 +46,37 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
Storage storage = enforcePublicTenantAndGetPublicTenantStorage(req);

if (token.startsWith("st_rt_")) {
String gid = null;
{
// introspect token to get gid
Map<String, String> formFields = new HashMap<>();
formFields.put("token", token);

HttpRequestForOry.Response response = OAuthProxyHelper.proxyFormPOST(
main, req, resp,
appIdentifier,
storage,
null, // clientIdToCheck
"/admin/oauth2/introspect", // pathProxy
true, // proxyToAdmin
false, // camelToSnakeCaseConversion
formFields,
new HashMap<>() // headers
);

if (response != null) {
JsonObject finalResponse = response.jsonResponse.getAsJsonObject();

try {
OAuth.verifyAndUpdateIntrospectRefreshTokenPayload(main, appIdentifier, storage, finalResponse, token);
gid = finalResponse.get("gid").getAsString();
} catch (StorageQueryException | TenantOrAppNotFoundException |
FeatureNotEnabledException | InvalidConfigException e) {
throw new ServletException(e);
}
}
}

// revoking refresh token
String clientId = InputParser.parseStringOrThrowError(input, "client_id", false);
String clientSecret = InputParser.parseStringOrThrowError(input, "client_secret", true);
Expand All @@ -70,7 +103,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
if (response != null) {
// Success response would mean that the clientId/secret has been validated
try {
OAuth.revokeRefreshToken(main, appIdentifier, storage, token);
OAuth.revokeRefreshToken(main, appIdentifier, storage, gid);
} catch (StorageQueryException | NoSuchAlgorithmException e) {
throw new ServletException(e);
}
Expand Down

0 comments on commit 930cd2c

Please sign in to comment.