Skip to content

Commit 881cd0b

Browse files
gregturnrwinch
authored andcommitted
Fix UsernamePasswordAuthenticationTokenMixin to handle null credentials/details
Resolves #4698
1 parent 82adf74 commit 881cd0b

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
package org.springframework.security.jackson2;
1818

19+
import java.io.IOException;
20+
import java.util.List;
21+
1922
import com.fasterxml.jackson.core.JsonParser;
2023
import com.fasterxml.jackson.core.JsonProcessingException;
2124
import com.fasterxml.jackson.core.type.TypeReference;
@@ -24,12 +27,10 @@
2427
import com.fasterxml.jackson.databind.JsonNode;
2528
import com.fasterxml.jackson.databind.ObjectMapper;
2629
import com.fasterxml.jackson.databind.node.MissingNode;
30+
2731
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
2832
import org.springframework.security.core.GrantedAuthority;
2933

30-
import java.io.IOException;
31-
import java.util.List;
32-
3334
/**
3435
* Custom deserializer for {@link UsernamePasswordAuthenticationToken}. At the time of deserialization
3536
* it will invoke suitable constructor depending on the value of <b>authenticated</b> property.
@@ -39,6 +40,7 @@
3940
* you can also registered it with your own mixin class.
4041
*
4142
* @author Jitendra Singh
43+
* @author Greg Turnquist
4244
* @see UsernamePasswordAuthenticationTokenMixin
4345
* @since 4.2
4446
*/
@@ -65,7 +67,13 @@ public UsernamePasswordAuthenticationToken deserialize(JsonParser jp, Deserializ
6567
} else {
6668
principal = principalNode.asText();
6769
}
68-
Object credentials = readJsonNode(jsonNode, "credentials").asText();
70+
JsonNode credentialsNode = readJsonNode(jsonNode, "credentials");
71+
Object credentials;
72+
if (credentialsNode.isNull()) {
73+
credentials = null;
74+
} else {
75+
credentials = credentialsNode.asText();
76+
}
6977
List<GrantedAuthority> authorities = mapper.readValue(
7078
readJsonNode(jsonNode, "authorities").traverse(mapper), new TypeReference<List<GrantedAuthority>>() {
7179
});
@@ -74,7 +82,12 @@ public UsernamePasswordAuthenticationToken deserialize(JsonParser jp, Deserializ
7482
} else {
7583
token = new UsernamePasswordAuthenticationToken(principal, credentials);
7684
}
77-
token.setDetails(readJsonNode(jsonNode, "details"));
85+
JsonNode detailsNode = readJsonNode(jsonNode, "details");
86+
if (detailsNode.isNull()) {
87+
token.setDetails(null);
88+
} else {
89+
token.setDetails(detailsNode);
90+
}
7891
return token;
7992
}
8093

core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@
3030
import org.springframework.security.core.authority.SimpleGrantedAuthority;
3131
import org.springframework.security.core.userdetails.User;
3232

33-
import static org.assertj.core.api.Assertions.assertThat;
33+
import static org.assertj.core.api.Assertions.*;
3434

3535
/**
3636
* @author Jitendra Singh
37+
* @author Greg Turnquist
3738
* @since 4.2
3839
*/
3940
public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixinTests {
@@ -150,6 +151,20 @@ public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithNonUs
150151
assertThat(token.getPrincipal()).isNotNull().isInstanceOf(NonUserPrincipal.class);
151152
}
152153

154+
@Test
155+
public void serializingThenDeserializingWithNoCredentialsOrDetailsShouldWork() throws IOException {
156+
// given
157+
UsernamePasswordAuthenticationToken original = new UsernamePasswordAuthenticationToken("Frodo", null);
158+
159+
// when
160+
String serialized = this.mapper.writeValueAsString(original);
161+
UsernamePasswordAuthenticationToken deserialized = this.mapper.readValue(serialized, UsernamePasswordAuthenticationToken.class);
162+
163+
// then
164+
assertThat(deserialized).isEqualTo(original);
165+
}
166+
167+
153168
private UsernamePasswordAuthenticationToken createToken() {
154169
User user = createDefaultUser();
155170
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());

0 commit comments

Comments
 (0)