Skip to content

Commit 3e6ef7e

Browse files
committed
#24 Implement token invalidation
1 parent 334c282 commit 3e6ef7e

File tree

1 file changed

+66
-7
lines changed

1 file changed

+66
-7
lines changed

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

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package io.github.javacoded78.jwthumble.storage;
22

33
import io.github.javacoded78.jwthumble.config.TokenParameters;
4+
import lombok.Getter;
45

6+
import java.util.Date;
57
import java.util.Map;
6-
import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.atomic.AtomicBoolean;
8+
import java.util.concurrent.ConcurrentHashMap;
9+
import java.util.concurrent.Executors;
10+
import java.util.concurrent.ScheduledExecutorService;
11+
import java.util.concurrent.TimeUnit;
12+
import java.util.concurrent.atomic.AtomicBoolean;
713

814
/**
915
* Basic implementation of TokenStorage.
@@ -13,13 +19,32 @@ public class TokenStorageImpl implements TokenStorage {
1319
/**
1420
* Inner map of key-value pairs.
1521
*/
16-
private final ConcurrentHashMap<String, String> tokens;
22+
private final ConcurrentHashMap<String, TokenEntry> tokens;
23+
24+
/**
25+
* Scheduled executor for cleanup tokens.
26+
*/
27+
private final ScheduledExecutorService scheduler;
1728

1829
/**
1930
* Creates an object.
2031
*/
2132
public TokenStorageImpl() {
2233
this.tokens = new ConcurrentHashMap<>();
34+
this.scheduler = Executors.newSingleThreadScheduledExecutor();
35+
scheduler.scheduleAtFixedRate(
36+
() -> {
37+
Date date = new Date();
38+
for (Map.Entry<String, TokenEntry> entry : tokens.entrySet()) {
39+
if (entry.getValue().isAfter(date)) {
40+
tokens.remove(entry.getKey());
41+
}
42+
}
43+
},
44+
0,
45+
1,
46+
TimeUnit.SECONDS
47+
);
2348
}
2449

2550
private String subjectTokenKey(final String subject,
@@ -34,7 +59,8 @@ public void save(final String token,
3459
params.getSubject(),
3560
params.getType()
3661
);
37-
tokens.put(tokenKey, token);
62+
TokenEntry entry = new TokenEntry(token, params.getExpiredAt());
63+
tokens.put(tokenKey, entry);
3864
}
3965

4066
@Override
@@ -44,7 +70,11 @@ public boolean exists(final String token,
4470
params.getSubject(),
4571
params.getType()
4672
);
47-
return token.equals(tokens.get(tokenKey));
73+
TokenEntry entry = tokens.get(tokenKey);
74+
if (entry == null) {
75+
return false;
76+
}
77+
return token.equals(entry.token);
4878
}
4979

5080
@Override
@@ -53,14 +83,18 @@ public String get(final TokenParameters params) {
5383
params.getSubject(),
5484
params.getType()
5585
);
56-
return tokens.get(tokenKey);
86+
TokenEntry entry = tokens.get(tokenKey);
87+
if (entry == null) {
88+
return null;
89+
}
90+
return entry.token;
5791
}
5892

5993
@Override
6094
public boolean remove(final String token) {
6195
AtomicBoolean deleted = new AtomicBoolean(false);
62-
for (Map.Entry<String, String> entry : tokens.entrySet()) {
63-
if (entry.getValue().equals(token)) {
96+
for (Map.Entry<String, TokenEntry> entry : tokens.entrySet()) {
97+
if (entry.getValue().token.equals(token)) {
6498
tokens.remove(entry.getKey());
6599
deleted.set(true);
66100
return true;
@@ -78,4 +112,29 @@ public boolean remove(final TokenParameters params) {
78112
return tokens.remove(tokenKey) != null;
79113
}
80114

115+
@Getter
116+
private static class TokenEntry {
117+
118+
/**
119+
* Token.
120+
*/
121+
private final String token;
122+
123+
/**
124+
* Expiration date.
125+
*/
126+
private final Date expiredAt;
127+
128+
TokenEntry(final String token,
129+
final Date expiredAt) {
130+
this.token = token;
131+
this.expiredAt = expiredAt;
132+
}
133+
134+
public boolean isAfter(final Date date) {
135+
return expiredAt.after(date);
136+
}
137+
138+
}
139+
81140
}

0 commit comments

Comments
 (0)