Skip to content

Commit

Permalink
fix: null props in access token (#500)
Browse files Browse the repository at this point in the history
* Update README.md

* fix: fixes handling of null props in access token payload

* chore: update changelog

* test: extend userData tests to check if null props work

Co-authored-by: Rishabh Poddar <[email protected]>
  • Loading branch information
porcellus and rishabhpoddar authored Sep 2, 2022
1 parent d540fac commit 3ea4356
Show file tree
Hide file tree
Showing 13 changed files with 87 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [unreleased]

### Bug fixes

- Fixed handling of `null` in access token payloads

## [3.16.0] - 2022-08-18

- Changes logging level of API start / finished & Cronjob start / finished to be `INFO` level instead of `DEBUG` level.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ public static TokenInfo createNewAccessToken(@Nonnull Main main, @Nonnull String
}
AccessTokenInfo accessToken = new AccessTokenInfo(sessionHandle, userId, refreshTokenHash1, expiryTime,
parentRefreshTokenHash1, userData, antiCsrfToken, now, lmrt);
String token = JWT.createJWT(new Gson().toJsonTree(accessToken), signingKey.privateKey, VERSION.V2);

String token = JWT.createJWT(Utils.toJsonTreeWithNulls(accessToken), signingKey.privateKey, VERSION.V2);
return new TokenInfo(token, expiryTime, now);

}
Expand All @@ -166,7 +167,7 @@ public static TokenInfo createNewAccessTokenV1(@Nonnull Main main, @Nonnull Stri
accessToken = new AccessTokenInfo(sessionHandle, userId, refreshTokenHash1, expiryTime, parentRefreshTokenHash1,
userData, antiCsrfToken, now, null);

String token = JWT.createJWT(new Gson().toJsonTree(accessToken), signingKey.privateKey, VERSION.V1);
String token = JWT.createJWT(Utils.toJsonTreeWithNulls(accessToken), signingKey.privateKey, VERSION.V1);
return new TokenInfo(token, expiryTime, now);

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import io.supertokens.utils.Utils;

public class SessionInformationHolder {

@Nonnull
Expand All @@ -44,4 +49,11 @@ public SessionInformationHolder(@Nonnull SessionInfo session, @Nullable TokenInf
this.idRefreshToken = idRefreshToken;
this.antiCsrfToken = antiCsrfToken;
}

public JsonObject toJsonObject() {
JsonObject json = new Gson().toJsonTree(this).getAsJsonObject();
json.add("session", Utils.toJsonTreeWithNulls(session));

return json;
}
}
6 changes: 6 additions & 0 deletions src/main/java/io/supertokens/utils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import io.supertokens.session.accessToken.AccessTokenSigningKey.KeyInfo;
Expand Down Expand Up @@ -295,4 +297,8 @@ public static JsonArray keyListToJson(List<KeyInfo> keys) {
}
return jwtSigningPublicKeyListJSON;
}

public static JsonElement toJsonTreeWithNulls(Object src) {
return new GsonBuilder().serializeNulls().create().toJsonTree(src);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
try {
SessionInformationHolder sessionInfo = Session.refreshSession(main, refreshToken, antiCsrfToken,
enableAntiCsrf);
JsonObject result = new JsonParser().parse(new Gson().toJson(sessionInfo)).getAsJsonObject();
JsonObject result = sessionInfo.toJsonObject();
result.addProperty("status", "OK");
super.sendJsonResponse(200, result, resp);
} catch (StorageQueryException | StorageTransactionLogicException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
SessionInformationHolder sessionInfo = Session.createNewSession(main, userId, userDataInJWT,
userDataInDatabase, enableAntiCsrf);

JsonObject result = new JsonParser().parse(new Gson().toJson(sessionInfo)).getAsJsonObject();
JsonObject result = sessionInfo.toJsonObject();

result.addProperty("status", "OK");

Expand Down Expand Up @@ -108,7 +108,10 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO
try {
SessionInfo sessionInfo = Session.getSession(main, sessionHandle);

JsonObject result = new JsonParser().parse(new Gson().toJson(sessionInfo)).getAsJsonObject();
JsonObject result = new Gson().toJsonTree(sessionInfo).getAsJsonObject();
result.add("userDataInJWT", Utils.toJsonTreeWithNulls(sessionInfo.userDataInJWT));
result.add("userDataInDatabase", Utils.toJsonTreeWithNulls(sessionInfo.userDataInDatabase));

result.addProperty("status", "OK");

super.sendJsonResponse(200, result, resp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
try {
SessionInformationHolder sessionInfo = Session.regenerateToken(main, accessToken, userDataInJWT);

JsonObject result = new JsonParser().parse(new Gson().toJson(sessionInfo)).getAsJsonObject();
JsonObject result = sessionInfo.toJsonObject();

result.addProperty("status", "OK");
super.sendJsonResponse(200, result, resp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
SessionInformationHolder sessionInfo = Session.getSession(main, accessToken, antiCsrfToken, enableAntiCsrf,
doAntiCsrfCheck);

JsonObject result = new JsonParser().parse(new Gson().toJson(sessionInfo)).getAsJsonObject();
JsonObject result = sessionInfo.toJsonObject();
result.addProperty("status", "OK");

result.addProperty("jwtSigningPublicKey",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.supertokens.test.session.api;

import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import io.supertokens.ProcessState;
import io.supertokens.test.TestingProcessManager;
Expand Down Expand Up @@ -363,6 +364,7 @@ public void successOutputWithValidRefreshTokenTest() throws Exception {

String userId = "userId";
JsonObject userDataInJWT = new JsonObject();
userDataInJWT.add("nullProp", JsonNull.INSTANCE);
userDataInJWT.addProperty("key", "value");
JsonObject userDataInDatabase = new JsonObject();
userDataInDatabase.addProperty("key", "value");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.supertokens.test.session.api;

import com.google.gson.JsonArray;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import io.supertokens.ProcessState;
import io.supertokens.test.TestingProcessManager;
Expand Down Expand Up @@ -138,6 +139,37 @@ public void successOutputCheckWithNoAntiCsrf() throws Exception {

}

@Test
public void successOutputCheckWithNullsInPayload() throws Exception {
String[] args = { "../" };
TestingProcessManager.TestingProcess process = TestingProcessManager.start(args);
assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));

String userId = "userId";

JsonObject innerObj = new JsonObject();
innerObj.add("nullProp", JsonNull.INSTANCE);
innerObj.addProperty("stringProp", "value");

JsonObject userDataInJWT = new JsonObject();
userDataInJWT.addProperty("stringProp", "value");
userDataInJWT.add("nullProp", JsonNull.INSTANCE);

JsonObject request = new JsonObject();
request.addProperty("userId", userId);
request.add("userDataInJWT", userDataInJWT);
request.add("userDataInDatabase", new JsonObject());
request.addProperty("enableAntiCsrf", false);

JsonObject response = HttpRequestForTesting.sendJsonPOSTRequest(process.getProcess(), "",
"http://localhost:3567/recipe/session", request, 1000, 1000, null, Utils.getCdiVersion2_9ForTests(),
"session");
checkSessionResponse(response, process, userId, userDataInJWT);

process.kill();
assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
}

@Test
public void badInputTest() throws Exception {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.supertokens.test.session.api;

import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.supertokens.ProcessState;
Expand Down Expand Up @@ -134,7 +135,7 @@ public void getRequestSuccessOutputCheckTest() throws Exception {

String sessionJsonInput = "{\n" + "\t\"userId\": \"UserID\",\n" + "\t\"userDataInJWT\": {\n"
+ "\t\t\"userData1\": \"temp1\",\n" + "\t\t\"userData2\": \"temp2\"\n" + "\t},\n"
+ "\t\"userDataInDatabase\": {\n" + "\t\t\"userData\": \"value\"\n" + "\t},\n"
+ "\t\"userDataInDatabase\": {\n" + "\t\t\"userData\": \"value\",\n" + "\t\t\"nullProp\": null\n\t},\n"
+ "\t\"customSigningKey\": \"string\",\n" + "\t\"enableAntiCsrf\": false\n" + "}";

JsonObject sessionBody = new JsonParser().parse(sessionJsonInput).getAsJsonObject();
Expand Down Expand Up @@ -195,6 +196,7 @@ public void putRequestSuccessOutputCheckTest() throws Exception {

JsonObject userDataInDatabase = new JsonObject();
userDataInDatabase.addProperty("userData1", "value1");
userDataInDatabase.add("nullProp", JsonNull.INSTANCE);

JsonObject putRequestBody = new JsonObject();
putRequestBody.addProperty("sessionHandle", "123abc");
Expand Down Expand Up @@ -228,6 +230,18 @@ public void putRequestSuccessOutputCheckTest() throws Exception {
assertEquals(response.entrySet().size(), 1);
assertEquals(response.get("status").getAsString(), "OK");

HashMap<String, String> map = new HashMap<>();
map.put("sessionHandle", session.get("session").getAsJsonObject().get("handle").getAsString());

response = HttpRequestForTesting.sendGETRequest(process.getProcess(), "",
"http://localhost:3567/recipe/session/data", map, 1000, 1000, null, Utils.getCdiVersion2_7ForTests(),
"session");

assertEquals(response.get("status").getAsString(), "OK");
assertEquals(response.entrySet().size(), 2);

assertEquals(response.get("userDataInDatabase").getAsJsonObject(), userDataInDatabase.getAsJsonObject());

process.kill();
assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.supertokens.test.session.api;

import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import io.supertokens.ProcessState;
import io.supertokens.session.accessToken.AccessToken;
Expand Down Expand Up @@ -75,6 +76,7 @@ public void testCallRegenerateAPIWithNewJwtPayloadAndCheckResponses() throws Exc

JsonObject newUserDataInJWT = new JsonObject();
newUserDataInJWT.addProperty("key2", "value2");
newUserDataInJWT.add("nullProp", JsonNull.INSTANCE);

JsonObject sessionRegenerateRequest = new JsonObject();
sessionRegenerateRequest.addProperty("accessToken", accessToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.supertokens.test.session.api;

import com.google.gson.JsonArray;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.supertokens.ProcessState;
Expand Down Expand Up @@ -55,6 +56,7 @@ public void successOutputCheckNoNewAccessToken() throws Exception {
String userId = "userId";
JsonObject userDataInJWT = new JsonObject();
userDataInJWT.addProperty("key", "value");
userDataInJWT.add("nullProp", JsonNull.INSTANCE);
JsonObject userDataInDatabase = new JsonObject();
userDataInDatabase.addProperty("key", "value");

Expand Down Expand Up @@ -109,6 +111,7 @@ public void successOutputCheckNewAccessToken() throws Exception {
String userId = "userId";
JsonObject userDataInJWT = new JsonObject();
userDataInJWT.addProperty("key", "value");
userDataInJWT.add("nullProp", JsonNull.INSTANCE);
JsonObject userDataInDatabase = new JsonObject();
userDataInDatabase.addProperty("key", "value");

Expand Down

0 comments on commit 3ea4356

Please sign in to comment.