Skip to content

Commit 11287ee

Browse files
authored
Merge pull request #23 from JavaCoDED78/#22
2 parents 8214aeb + c3bc164 commit 11287ee

File tree

9 files changed

+266
-1
lines changed

9 files changed

+266
-1
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.github.javacoded78.jwthumble.service;
2+
3+
import io.github.javacoded78.jwthumble.config.TokenParameters;
4+
5+
/**
6+
* Interface if PersistentTokenService.
7+
*/
8+
public interface PersistentTokenService extends TokenService {
9+
10+
/**
11+
* Removes JWT token from storage. Method removes all entries
12+
* of the same token.
13+
*
14+
* @param token JWT token to be removed
15+
* @return true - if JWT token was removed, false - otherwise
16+
*/
17+
boolean invalidate(String token);
18+
19+
/**
20+
* Removes JWT token from storage.
21+
*
22+
* @param params params of JWT token
23+
* @return true - if JWT token was removed, false - otherwise
24+
*/
25+
boolean invalidate(TokenParameters params);
26+
27+
}

src/main/java/io/github/javacoded78/jwthumble/service/PersistentTokenServiceImpl.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
/**
1818
* Implementation of TokenService with JWT token storage.
1919
*/
20-
public class PersistentTokenServiceImpl implements TokenService {
20+
public class PersistentTokenServiceImpl implements PersistentTokenService {
2121

2222
/**
2323
* Secret key for verifying JWT token.
@@ -148,4 +148,14 @@ public Map<String, Object> claims(final String token) {
148148
return new HashMap<>(claims.getPayload());
149149
}
150150

151+
@Override
152+
public boolean invalidate(final String token) {
153+
return tokenStorage.remove(token);
154+
}
155+
156+
@Override
157+
public boolean invalidate(final TokenParameters params) {
158+
return tokenStorage.remove(params);
159+
}
160+
151161
}

src/main/java/io/github/javacoded78/jwthumble/storage/RedisTokenStorageImpl.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,35 @@ public String get(final TokenParameters params) {
122122
}
123123
}
124124

125+
@Override
126+
public boolean remove(final String token) {
127+
try (Jedis jedis = jedisPool.getResource()) {
128+
String script = """
129+
local keys = redis.call('keys', ARGV[1])
130+
for _, key in ipairs(keys) do
131+
redis.call('del', key)
132+
end
133+
return #keys > 0
134+
""";
135+
Long result = (Long) jedis.eval(
136+
script,
137+
0,
138+
"*",
139+
token
140+
);
141+
return result != null && result > 0;
142+
}
143+
}
144+
145+
@Override
146+
public boolean remove(final TokenParameters params) {
147+
try (Jedis jedis = jedisPool.getResource()) {
148+
String tokenKey = redisSchema.subjectTokenKey(
149+
params.getSubject(),
150+
params.getType()
151+
);
152+
return jedis.del(tokenKey) > 0;
153+
}
154+
}
155+
125156
}

src/main/java/io/github/javacoded78/jwthumble/storage/TokenStorage.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,20 @@ boolean exists(String token,
3434
*/
3535
String get(TokenParameters params);
3636

37+
/**
38+
* Removes JWT token from storage.
39+
*
40+
* @param token JWT token to be removed
41+
* @return true - if JWT token was removed, false - otherwise
42+
*/
43+
boolean remove(String token);
44+
45+
/**
46+
* Removes JWT token from storage.
47+
*
48+
* @param params params of JWT token
49+
* @return true - if JWT token was removed, false - otherwise
50+
*/
51+
boolean remove(TokenParameters params);
52+
3753
}

src/main/java/io/github/javacoded78/jwthumble/storage/TokenStorageImpl.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import java.util.HashMap;
66
import java.util.Map;
7+
import java.util.concurrent.atomic.AtomicBoolean;
78

89
/**
910
* Basic implementation of TokenStorage. Not thread-safe.
@@ -56,4 +57,26 @@ public String get(final TokenParameters params) {
5657
return tokens.get(tokenKey);
5758
}
5859

60+
@Override
61+
public boolean remove(final String token) {
62+
AtomicBoolean deleted = new AtomicBoolean(false);
63+
for (Map.Entry<String, String> entry : tokens.entrySet()) {
64+
if (entry.getValue().equals(token)) {
65+
tokens.remove(entry.getKey());
66+
deleted.set(true);
67+
return true;
68+
}
69+
}
70+
return deleted.get();
71+
}
72+
73+
@Override
74+
public boolean remove(final TokenParameters params) {
75+
String tokenKey = subjectTokenKey(
76+
params.getSubject(),
77+
params.getType()
78+
);
79+
return tokens.remove(tokenKey) != null;
80+
}
81+
5982
}

src/test/java/io/github/javacoded78/jwthumble/fake/FakeTokenStorageImpl.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.github.javacoded78.jwthumble.storage.TokenStorage;
55
import java.util.HashMap;
66
import java.util.Map;
7+
import java.util.concurrent.atomic.AtomicBoolean;
78

89
public class FakeTokenStorageImpl implements TokenStorage {
910

@@ -43,4 +44,26 @@ public boolean exists(final String token,
4344
return token.equals(tokens.get(tokenKey));
4445
}
4546

47+
@Override
48+
public boolean remove(final String token) {
49+
AtomicBoolean deleted = new AtomicBoolean(false);
50+
for (Map.Entry<String, String> entry : tokens.entrySet()) {
51+
if (entry.getValue().equals(token)) {
52+
tokens.remove(entry.getKey());
53+
deleted.set(true);
54+
return true;
55+
}
56+
}
57+
return deleted.get();
58+
}
59+
60+
@Override
61+
public boolean remove(final TokenParameters params) {
62+
String tokenKey = subjectTokenKey(
63+
params.getSubject(),
64+
params.getType()
65+
);
66+
return tokens.remove(tokenKey) != null;
67+
}
68+
4669
}

src/test/java/io/github/javacoded78/jwthumble/service/PersistentTokenServiceImplTests.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import static org.junit.jupiter.api.Assertions.assertEquals;
1616
import static org.junit.jupiter.api.Assertions.assertFalse;
17+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
1718
import static org.junit.jupiter.api.Assertions.assertNotNull;
1819
import static org.junit.jupiter.api.Assertions.assertTrue;
1920

@@ -167,4 +168,58 @@ void claims_ReturnsCorrectClaims() {
167168
assertEquals(123, claims.get("key2"));
168169
}
169170

171+
@Test
172+
void invalidate_Token() {
173+
TokenParameters params = TokenParameters.builder(
174+
subject,
175+
type,
176+
duration
177+
)
178+
.build();
179+
String token = tokenService.create(params);
180+
181+
tokenService.invalidate(token);
182+
183+
try {
184+
Thread.sleep(2000);
185+
} catch (InterruptedException ignored) {
186+
}
187+
188+
TokenParameters newParams = TokenParameters.builder(
189+
subject,
190+
type,
191+
duration
192+
)
193+
.build();
194+
String newToken = tokenService.create(newParams);
195+
assertNotEquals(token, newToken);
196+
}
197+
198+
@Test
199+
void invalidate_SubjectAndType() {
200+
TokenParameters params = TokenParameters.builder(
201+
subject,
202+
type,
203+
duration
204+
)
205+
.build();
206+
String token = tokenService.create(params);
207+
208+
tokenService.invalidate(params);
209+
210+
try {
211+
Thread.sleep(2000);
212+
} catch (InterruptedException ignored) {
213+
}
214+
215+
TokenParameters newParams = TokenParameters.builder(
216+
subject,
217+
type,
218+
duration
219+
)
220+
.build();
221+
String newToken = tokenService.create(newParams);
222+
assertNotEquals(token, newToken);
223+
}
224+
170225
}

src/test/java/io/github/javacoded78/jwthumble/storage/RedisTokenStorageImplTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,44 @@ void get_NonExistingToken_ReturnsNull() {
127127
assertNull(tokenStorage.get(params));
128128
}
129129

130+
@Test
131+
void invalidate_Token() {
132+
TokenParameters params = TokenParameters.builder(
133+
subject,
134+
type,
135+
duration
136+
)
137+
.build();
138+
String token = "testToken";
139+
tokenStorage.save(
140+
token,
141+
params
142+
);
143+
144+
tokenStorage.remove(token);
145+
146+
String existingToken = tokenStorage.get(params);
147+
assertNull(existingToken);
148+
}
149+
150+
@Test
151+
void invalidate_SubjectAndType() {
152+
TokenParameters params = TokenParameters.builder(
153+
subject,
154+
type,
155+
duration
156+
)
157+
.build();
158+
String token = "testToken";
159+
tokenStorage.save(
160+
token,
161+
params
162+
);
163+
164+
tokenStorage.remove(params);
165+
166+
String existingToken = tokenStorage.get(params);
167+
assertNull(existingToken);
168+
}
169+
130170
}

src/test/java/io/github/javacoded78/jwthumble/storage/TokenStorageImplTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,45 @@ void get_NonExistingToken_ReturnsNull() {
101101

102102
assertNull(tokenStorage.get(params));
103103
}
104+
105+
@Test
106+
void invalidate_Token() {
107+
TokenParameters params = TokenParameters.builder(
108+
subject,
109+
type,
110+
duration
111+
)
112+
.build();
113+
String token = "testToken";
114+
tokenStorage.save(
115+
token,
116+
params
117+
);
118+
119+
tokenStorage.remove(token);
120+
121+
String existingToken = tokenStorage.get(params);
122+
assertNull(existingToken);
123+
}
124+
125+
@Test
126+
void invalidate_SubjectAndType() {
127+
TokenParameters params = TokenParameters.builder(
128+
subject,
129+
type,
130+
duration
131+
)
132+
.build();
133+
String token = "testToken";
134+
tokenStorage.save(
135+
token,
136+
params
137+
);
138+
139+
tokenStorage.remove(params);
140+
141+
String existingToken = tokenStorage.get(params);
142+
assertNull(existingToken);
143+
}
104144
}
105145

0 commit comments

Comments
 (0)