Skip to content

Commit

Permalink
fix: pr comments
Browse files Browse the repository at this point in the history
  • Loading branch information
sattvikc committed Sep 11, 2024
1 parent 3e94443 commit b79ddfa
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 180 deletions.
52 changes: 4 additions & 48 deletions src/main/java/io/supertokens/oauth/OAuth.java
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,13 @@ private static void checkNonSuccessResponse(HttpRequest.Response response) throw
public static JsonObject transformTokens(Main main, AppIdentifier appIdentifier, Storage storage, JsonObject jsonBody, String iss, boolean useDynamicKey) throws IOException, JWTException, InvalidKeyException, NoSuchAlgorithmException, StorageQueryException, StorageTransactionLogicException, UnsupportedJWTSigningAlgorithmException, TenantOrAppNotFoundException, InvalidKeySpecException, JWTCreationException, InvalidConfigException {
if (jsonBody.has("access_token")) {
String accessToken = jsonBody.get("access_token").getAsString();
accessToken = reSignToken(appIdentifier, main, accessToken, iss, SessionTokenType.ACCESS_TOKEN, useDynamicKey, 0);
accessToken = OAuthToken.reSignToken(appIdentifier, main, accessToken, iss, OAuthToken.TokenType.ACCESS_TOKEN, useDynamicKey, 0);
jsonBody.addProperty("access_token", accessToken);
}

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

Expand All @@ -277,35 +277,6 @@ public static JsonObject transformTokens(Main main, AppIdentifier appIdentifier,
return jsonBody;
}

private static String reSignToken(AppIdentifier appIdentifier, Main main, String token, String iss, SessionTokenType tokenType, boolean useDynamicSigningKey, int retryCount) throws IOException, JWTException, InvalidKeyException, NoSuchAlgorithmException, StorageQueryException, StorageTransactionLogicException, UnsupportedJWTSigningAlgorithmException, TenantOrAppNotFoundException, InvalidKeySpecException, JWTCreationException, InvalidConfigException {
// Load the JWKS from the specified URL
JsonObject payload = JWT.getPayloadWithoutVerifying(token).payload;

// move keys in ext to root
if (tokenType == SessionTokenType.ACCESS_TOKEN && payload.has("ext")) {
JsonObject ext = payload.getAsJsonObject("ext");
for (Map.Entry<String, JsonElement> entry : ext.entrySet()) {
payload.add(entry.getKey(), entry.getValue());
}
payload.remove("ext");
}
payload.addProperty("iss", iss);
payload.addProperty("stt", tokenType.getValue());

JWTSigningKeyInfo keyToUse;
if (useDynamicSigningKey) {
keyToUse = Utils.getJWTSigningKeyInfoFromKeyInfo(
SigningKeys.getInstance(appIdentifier, main).getLatestIssuedDynamicKey());
} else {
keyToUse = SigningKeys.getInstance(appIdentifier, main)
.getStaticKeyForAlgorithm(JWTSigningKey.SupportedAlgorithms.RS256);
}

token = JWTSigningFunctions.createJWTToken(JWTSigningKey.SupportedAlgorithms.RS256, new HashMap<>(),
payload, null, payload.get("exp").getAsLong(), payload.get("iat").getAsLong(), keyToUse);
return token;
}

public static void addClientId(Main main, AppIdentifier appIdentifier, Storage storage, String clientId) throws StorageQueryException, OAuth2ClientAlreadyExistsForAppException {
OAuthStorage oauthStorage = StorageUtils.getOAuthStorage(storage);
oauthStorage.addClientForApp(appIdentifier, clientId);
Expand Down Expand Up @@ -366,26 +337,11 @@ public static JsonElement convertSnakeCaseToCamelCaseRecursively(JsonElement jso

}

public static enum SessionTokenType {
ACCESS_TOKEN(1),
ID_TOKEN(2);

private final int value;

SessionTokenType(int value) {
this.value = value;
}

public int getValue() {
return value;
}
}

public static JsonObject introspectAccessToken(Main main, AppIdentifier appIdentifier, Storage storage,
String token) throws StorageQueryException, StorageTransactionLogicException, TenantOrAppNotFoundException, UnsupportedJWTSigningAlgorithmException {
try {
JsonObject payload = AccessToken.getPayloadFromAccessToken(appIdentifier, main, token);
if (payload.has("stt") && payload.get("stt").getAsInt() == SessionTokenType.ACCESS_TOKEN.value) {
JsonObject payload = OAuthToken.getPayloadFromJWTToken(appIdentifier, main, token);
if (payload.has("stt") && payload.get("stt").getAsInt() == OAuthToken.TokenType.ACCESS_TOKEN.getValue()) {
payload.addProperty("active", true);
payload.addProperty("token_type", "Bearer");
payload.addProperty("token_use", "access_token");
Expand Down
119 changes: 119 additions & 0 deletions src/main/java/io/supertokens/oauth/OAuthToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package io.supertokens.oauth;

import com.auth0.jwt.exceptions.JWTCreationException;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.supertokens.Main;
import io.supertokens.exceptions.TryRefreshTokenException;
import io.supertokens.jwt.JWTSigningFunctions;
import io.supertokens.jwt.exceptions.UnsupportedJWTSigningAlgorithmException;
import io.supertokens.pluginInterface.exceptions.StorageQueryException;
import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException;
import io.supertokens.pluginInterface.jwt.JWTAsymmetricSigningKeyInfo;
import io.supertokens.pluginInterface.jwt.JWTSigningKeyInfo;
import io.supertokens.pluginInterface.multitenancy.AppIdentifier;
import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException;
import io.supertokens.session.jwt.JWT;
import io.supertokens.session.jwt.JWT.JWTException;
import io.supertokens.signingkeys.JWTSigningKey;
import io.supertokens.signingkeys.SigningKeys;
import io.supertokens.utils.Utils;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class OAuthToken {
public enum TokenType {
ACCESS_TOKEN(1),
ID_TOKEN(2);

private final int value;

TokenType(int value) {
this.value = value;
}

public int getValue() {
return value;
}
}

public static JsonObject getPayloadFromJWTToken(AppIdentifier appIdentifier,
@Nonnull Main main, @Nonnull String token)
throws TenantOrAppNotFoundException, TryRefreshTokenException, StorageQueryException,
UnsupportedJWTSigningAlgorithmException, StorageTransactionLogicException {
List<JWTSigningKeyInfo> keyInfoList = SigningKeys.getInstance(appIdentifier, main).getAllKeys();
Exception error = null;
JWT.JWTInfo jwtInfo = null;
JWT.JWTPreParseInfo preParseJWTInfo = null;
try {
preParseJWTInfo = JWT.preParseJWTInfo(token);
} catch (JWTException e) {
// This basically should never happen, but it means, that the token structure is
// wrong, can't verify
throw new TryRefreshTokenException(e);
}

for (JWTSigningKeyInfo keyInfo : keyInfoList) {
try {
jwtInfo = JWT.verifyJWTAndGetPayload(preParseJWTInfo,
((JWTAsymmetricSigningKeyInfo) keyInfo).publicKey);
error = null;
break;
} catch (NoSuchAlgorithmException e) {
// This basically should never happen, but it means, that can't verify any
// tokens, no need to retry
throw new TryRefreshTokenException(e);
} catch (KeyException | JWTException e) {
error = e;
}
}

if (jwtInfo == null) {
throw new TryRefreshTokenException(error);
}

if (jwtInfo.payload.get("exp").getAsLong() * 1000 < System.currentTimeMillis()) {
throw new TryRefreshTokenException("Access token expired");
}

return jwtInfo.payload;
}

public static String reSignToken(AppIdentifier appIdentifier, Main main, String token, String iss, TokenType tokenType, boolean useDynamicSigningKey, int retryCount) throws IOException, JWTException, InvalidKeyException, NoSuchAlgorithmException, StorageQueryException, StorageTransactionLogicException, UnsupportedJWTSigningAlgorithmException, TenantOrAppNotFoundException, InvalidKeySpecException,
JWTCreationException {
// Load the JWKS from the specified URL
JsonObject payload = JWT.getPayloadWithoutVerifying(token).payload;

// move keys in ext to root
if (tokenType == TokenType.ACCESS_TOKEN && payload.has("ext")) {
JsonObject ext = payload.getAsJsonObject("ext");
for (Map.Entry<String, JsonElement> entry : ext.entrySet()) {
payload.add(entry.getKey(), entry.getValue());
}
payload.remove("ext");
}
payload.addProperty("iss", iss);
payload.addProperty("stt", tokenType.getValue());

JWTSigningKeyInfo keyToUse;
if (useDynamicSigningKey) {
keyToUse = Utils.getJWTSigningKeyInfoFromKeyInfo(
SigningKeys.getInstance(appIdentifier, main).getLatestIssuedDynamicKey());
} else {
keyToUse = SigningKeys.getInstance(appIdentifier, main)
.getStaticKeyForAlgorithm(JWTSigningKey.SupportedAlgorithms.RS256);
}

token = JWTSigningFunctions.createJWTToken(JWTSigningKey.SupportedAlgorithms.RS256, new HashMap<>(),
payload, null, payload.get("exp").getAsLong(), payload.get("iat").getAsLong(), keyToUse);
return token;
}
}

This file was deleted.

This file was deleted.

35 changes: 0 additions & 35 deletions src/main/java/io/supertokens/oauth/exceptions/OAuthException.java

This file was deleted.

40 changes: 0 additions & 40 deletions src/main/java/io/supertokens/session/accessToken/AccessToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,46 +56,6 @@

public class AccessToken {

public static JsonObject getPayloadFromAccessToken(AppIdentifier appIdentifier,
@Nonnull Main main, @Nonnull String token)
throws TenantOrAppNotFoundException, TryRefreshTokenException, StorageQueryException,
UnsupportedJWTSigningAlgorithmException, StorageTransactionLogicException {
List<JWTSigningKeyInfo> keyInfoList = SigningKeys.getInstance(appIdentifier, main).getAllKeys();
Exception error = null;
JWT.JWTInfo jwtInfo = null;
JWT.JWTPreParseInfo preParseJWTInfo = null;
try {
preParseJWTInfo = JWT.preParseJWTInfo(token);
} catch (JWTException e) {
// This basically should never happen, but it means, that the token structure is wrong, can't verify
throw new TryRefreshTokenException(e);
}

for (JWTSigningKeyInfo keyInfo : keyInfoList) {
try {
jwtInfo = JWT.verifyJWTAndGetPayload(preParseJWTInfo,
((JWTAsymmetricSigningKeyInfo) keyInfo).publicKey);
error = null;
break;
} catch (NoSuchAlgorithmException e) {
// This basically should never happen, but it means, that can't verify any tokens, no need to retry
throw new TryRefreshTokenException(e);
} catch (KeyException | JWTException e) {
error = e;
}
}

if (jwtInfo == null) {
throw new TryRefreshTokenException(error);
}

if (jwtInfo.payload.get("exp").getAsLong() * 1000 < System.currentTimeMillis()) {
throw new TryRefreshTokenException("Access token expired");
}

return jwtInfo.payload;
}

// TODO: device fingerprint - store hash of this in JWT.

private static AccessTokenInfo getInfoFromAccessToken(AppIdentifier appIdentifier,
Expand Down

0 comments on commit b79ddfa

Please sign in to comment.