Skip to content

Commit 7e49545

Browse files
committed
Include csrf in jwt. Add double submit csrf validation
1 parent a561ba4 commit 7e49545

File tree

4 files changed

+26
-6
lines changed

4 files changed

+26
-6
lines changed

security/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<groupId>com.evalvis</groupId>
1313
<artifactId>security</artifactId>
14-
<version>2.2.2</version>
14+
<version>2.3.0</version>
1515
<name>security</name>
1616

1717
<distributionManagement>

security/src/main/java/com/evalvis/security/JwtFilter.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ protected void doFilterInternal(
3333
JwtToken.existing(request, key.value(), blacklistedJwtTokenRedisRepository)
3434
.ifPresent(
3535
token -> {
36-
if (token.tokenIsValid()) {
36+
if (token.tokenIsValid() && csrfDoubleSubmitTokenIsValid(request, token)) {
3737
UserDetails userDetails = new User(token.username(), null);
3838
UsernamePasswordAuthenticationToken authentication =
3939
new UsernamePasswordAuthenticationToken(
@@ -51,4 +51,8 @@ protected void doFilterInternal(
5151
}
5252
filterChain.doFilter(request, response);
5353
}
54+
55+
private boolean csrfDoubleSubmitTokenIsValid(HttpServletRequest request, JwtToken token) {
56+
return request.getHeader("X-CSRF-TOKEN").equals(token.csrfToken());
57+
}
5458
}

security/src/main/java/com/evalvis/security/JwtToken.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
import org.springframework.util.StringUtils;
1313

1414
import javax.crypto.SecretKey;
15-
import java.util.Arrays;
16-
import java.util.Date;
17-
import java.util.Optional;
15+
import java.security.SecureRandom;
16+
import java.util.*;
1817

1918
public final class JwtToken {
2019
private static final Logger logger = LoggerFactory.getLogger(JwtToken.class);
@@ -31,6 +30,7 @@ public static JwtToken create(
3130
Jwts
3231
.builder()
3332
.subject(((User) authentication.getPrincipal()).getUsername())
33+
.claim("csrfToken", generateCsrfToken())
3434
.issuedAt(new Date())
3535
.expiration(new Date((new Date()).getTime() + jwtExpirationMs))
3636
.signWith(key)
@@ -40,6 +40,12 @@ public static JwtToken create(
4040
);
4141
}
4242

43+
public static String generateCsrfToken() {
44+
byte[] randomBytes = new byte[32];
45+
new SecureRandom().nextBytes(randomBytes);
46+
return Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes);
47+
}
48+
4349
public static Optional<JwtToken> existing(
4450
HttpServletRequest request, SecretKey key, BlacklistedJwtTokenRepository blacklistedJwtTokenRepository
4551
) {
@@ -89,6 +95,12 @@ public Date expirationDate() {
8995
return Jwts.parser().verifyWith(key).build().parseSignedClaims(token).getPayload().getExpiration();
9096
}
9197

98+
public String csrfToken() {
99+
return Jwts.parser().verifyWith(key).build().parseSignedClaims(token).getPayload().get(
100+
"csrfToken", String.class
101+
);
102+
}
103+
92104
public boolean tokenIsValid() {
93105
try {
94106
Jwts.parser().verifyWith(key).build().parse(token);

security/src/test/java/com/evalvis/security/ITTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.springframework.test.context.ActiveProfiles;
1111

1212
import java.io.IOException;
13+
import java.util.Map;
1314

1415
import static org.junit.jupiter.api.Assertions.*;
1516

@@ -52,7 +53,10 @@ void blacklistsToken() {
5253
private void login(JwtToken token) {
5354
try {
5455
jwtFilter.doFilterInternal(
55-
new FakeHttpServletRequest(new Cookie[]{new Cookie("jwt", token.value())}),
56+
new FakeHttpServletRequest(
57+
Map.of("X-CSRF-TOKEN", token.csrfToken()),
58+
new Cookie[]{new Cookie("jwt", token.value())}
59+
),
5660
new FakeHttpServletResponse(),
5761
new FakeFilterChain()
5862
);

0 commit comments

Comments
 (0)