Skip to content

Commit 55a89f6

Browse files
author
zihluwang
committed
docs: added Javadoc
1 parent 6326f1b commit 55a89f6

File tree

11 files changed

+400
-30
lines changed

11 files changed

+400
-30
lines changed

simple-jwt/src/main/java/com/onixbyte/jwt/TokenCreator.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,29 @@
1818
package com.onixbyte.jwt;
1919

2020
/**
21+
* Interface for creating and signing JSON Web Tokens (JWTs).
22+
* <p>
23+
* Defines a contract for implementations that generate signed JWTs from a given payload. The
24+
* resulting token is typically a string in the format "header.payload.signature", where the
25+
* signature is created using a cryptographic algorithm specific to the implementation.
2126
*
27+
* @author zihluwang
2228
*/
2329
public interface TokenCreator {
2430

31+
/**
32+
* Signs a token payload to create a JWT.
33+
* <p>
34+
* Takes a {@link TokenPayload} object, serialises its claims, and generates a signed
35+
* JWT string. The specific signing algorithm (e.g., HMAC, RSA, ECDSA) depends on
36+
* the implementation.
37+
*
38+
* @param payload the {@link TokenPayload} containing claims to include in the token
39+
* @return the signed JWT as a string in the format "header.payload.signature"
40+
* @throws IllegalArgumentException if the payload cannot be serialised to JSON due to invalid
41+
* data or structure, or if the signing process fails due to
42+
* configuration issues
43+
*/
2544
String sign(TokenPayload payload);
2645

2746
}
Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,47 @@
1+
/*
2+
* Copyright (C) 2024-2025 OnixByte.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
*
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
118
package com.onixbyte.jwt;
219

20+
/**
21+
* Interface for managing JSON Web Tokens (JWTs) with support for signing, verification, and
22+
* payload extraction.
23+
* <p>
24+
* Combines the functionality of {@link TokenCreator} for creating signed JWTs and
25+
* {@link TokenResolver} for verifying and parsing them, while adding the ability to extract the
26+
* payload as a custom type {@code T}. Implementations are expected to handle both token generation
27+
* and resolution, providing a unified interface for JWT operations.
28+
*
29+
* @param <T> the type of object to which the token payload will be converted
30+
* @author zihluwang
31+
*/
332
public interface TokenManager<T> extends TokenCreator, TokenResolver {
433

34+
/**
35+
* Extracts the payload from a JWT and converts it to an object of type {@code T}.
36+
* <p>
37+
* Retrieves the payload from the token and transforms it into the specified type using an
38+
* implementation-specific mechanism, such as an adapter or mapper.
39+
*
40+
* @param token the JWT string from which to extract the payload
41+
* @return the payload converted to an object of type {@code T}
42+
* @throws IllegalArgumentException if the token is malformed, the signature is invalid, or the
43+
* payload cannot be deserialised or converted to
44+
* type {@code T}
45+
*/
546
T extract(String token);
6-
7-
}
47+
}

simple-jwt/src/main/java/com/onixbyte/jwt/TokenPayload.java

Lines changed: 148 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,78 +24,208 @@
2424
import java.util.*;
2525

2626
/**
27+
* A builder-style class for constructing JSON Web Token (JWT) payloads.
28+
* <p>
29+
* Provides a fluent interface to set standard registered claims (e.g., subject, issuer, audience)
30+
* and custom claims for a JWT payload. The class supports chaining method calls to build the
31+
* payload incrementally, which can then be retrieved as a map for use in JWT creation. Ensures that
32+
* registered claims are set using dedicated methods to prevent misuse.
2733
*
34+
* @author zihluwang
2835
*/
2936
public class TokenPayload {
3037

38+
/**
39+
* Creates a new instance of {@link TokenPayload} with an empty payload.
40+
* <p>
41+
* Initialises the payload with empty collections for claims and audiences, ready for
42+
* configuration via the builder methods.
43+
*
44+
* @return a new {@link TokenPayload} instance
45+
*/
3146
public static TokenPayload createPayload() {
3247
return new TokenPayload();
3348
}
3449

50+
/**
51+
* The map storing custom claims for the JWT payload.
52+
*/
3553
private final Map<String, Object> payload;
54+
55+
/**
56+
* The list of audience identifiers for the JWT.
57+
*/
3658
private final List<String> audiences;
3759

60+
/**
61+
* The subject of the JWT, identifying the principal.
62+
*/
3863
private String subject;
64+
65+
/**
66+
* The issuer of the JWT, identifying the entity that issued the token.
67+
*/
3968
private String issuer;
69+
70+
/**
71+
* The unique identifier for the JWT.
72+
*/
4073
private String tokenId;
74+
75+
/**
76+
* The expiration time of the JWT, as seconds since the Unix epoch.
77+
*/
4178
private Long expiresAt;
79+
80+
/**
81+
* The time before which the JWT must not be accepted, as seconds since the Unix epoch.
82+
*/
4283
private Long notBefore;
84+
85+
/**
86+
* The issuance time of the JWT, as seconds since the Unix epoch.
87+
*/
4388
private Long issuedAt;
4489

4590
/**
46-
* Private constructor to prevent instantiation of this utility class.
91+
* Private constructor to enforce use of the factory method.
92+
* <p>
93+
* Initialises the internal collections for storing claims and audiences, preventing direct
94+
* instantiation outside the class.
4795
*/
4896
private TokenPayload() {
4997
payload = new HashMap<>();
5098
audiences = new ArrayList<>();
5199
}
52100

101+
/**
102+
* Adds a single audience to the JWT payload.
103+
* <p>
104+
* Appends the specified audience identifier to the list of audiences, allowing the token to be
105+
* validated for multiple recipients.
106+
*
107+
* @param audience the audience identifier to add
108+
* @return this {@link TokenPayload} instance for method chaining
109+
*/
53110
public TokenPayload withAudience(String audience) {
54111
audiences.add(audience);
55112
return this;
56113
}
57114

115+
/**
116+
* Adds multiple audiences to the JWT payload.
117+
* <p>
118+
* Appends all provided audience identifiers to the list of audiences, enabling the token to be
119+
* validated for multiple recipients.
120+
*
121+
* @param audiences the audience identifiers to add
122+
* @return this {@link TokenPayload} instance for method chaining
123+
*/
58124
public TokenPayload withAudiences(String... audiences) {
59125
this.audiences.addAll(Arrays.asList(audiences));
60126
return this;
61127
}
62128

129+
/**
130+
* Sets the subject of the JWT payload.
131+
* <p>
132+
* Specifies the principal that is the subject of the token, typically identifying the user or
133+
* entity the token represents.
134+
*
135+
* @param subject the subject identifier
136+
* @return this {@link TokenPayload} instance for method chaining
137+
*/
63138
public TokenPayload withSubject(String subject) {
64139
this.subject = subject;
65140
return this;
66141
}
67142

143+
/**
144+
* Sets the issuer of the JWT payload.
145+
* <p>
146+
* Specifies the entity that issued the token, allowing recipients to verify the token's origin.
147+
*
148+
* @param issuer the issuer identifier
149+
* @return this {@link TokenPayload} instance for method chaining
150+
*/
68151
public TokenPayload withIssuer(String issuer) {
69152
this.issuer = issuer;
70153
return this;
71154
}
72155

156+
/**
157+
* Sets the unique identifier for the JWT payload.
158+
* <p>
159+
* Assigns a unique token ID to the JWT, which can be used to prevent token reuse or for
160+
* tracking purposes.
161+
*
162+
* @param tokenId the unique token identifier
163+
* @return this {@link TokenPayload} instance for method chaining
164+
*/
73165
public TokenPayload withTokenId(String tokenId) {
74166
this.tokenId = tokenId;
75167
return this;
76168
}
77169

170+
/**
171+
* Sets the expiration time for the JWT payload.
172+
* <p>
173+
* Specifies when the token expires, converted to seconds since the Unix epoch based on the
174+
* system's default time zone.
175+
*
176+
* @param expiresAt the expiration time as a {@link LocalDateTime}
177+
* @return this {@link TokenPayload} instance for method chaining
178+
*/
78179
public TokenPayload withExpiresAt(LocalDateTime expiresAt) {
79180
this.expiresAt = expiresAt.atZone(ZoneId.systemDefault())
80181
.toInstant()
81182
.getEpochSecond();
82183
return this;
83184
}
84185

186+
/**
187+
* Sets the time before which the JWT must not be accepted.
188+
* <p>
189+
* Specifies the "not before" time, converted to seconds since the Unix epoch based on the
190+
* system's default time zone.
191+
*
192+
* @param notBefore the time before which the token is invalid, as a {@link LocalDateTime}
193+
* @return this {@link TokenPayload} instance for method chaining
194+
*/
85195
public TokenPayload withNotBefore(LocalDateTime notBefore) {
86196
this.notBefore = notBefore.atZone(ZoneId.systemDefault())
87197
.toInstant()
88198
.getEpochSecond();
89199
return this;
90200
}
91201

202+
/**
203+
* Sets the issuance time for the JWT payload.
204+
* <p>
205+
* Specifies when the token was issued, converted to seconds since the Unix epoch based on the
206+
* system's default time zone.
207+
*
208+
* @param issuedAt the issuance time as a {@link LocalDateTime}
209+
* @return this {@link TokenPayload} instance for method chaining
210+
*/
92211
public TokenPayload withIssuedAt(LocalDateTime issuedAt) {
93212
this.issuedAt = issuedAt.atZone(ZoneId.systemDefault())
94213
.toInstant()
95214
.getEpochSecond();
96215
return this;
97216
}
98217

218+
/**
219+
* Adds a custom claim to the JWT payload.
220+
* <p>
221+
* Stores a custom key-value pair in the payload, provided the key is not a registered claim.
222+
* Registered claims must be set using their dedicated methods to ensure proper handling.
223+
*
224+
* @param name the name of the custom claim
225+
* @param value the value of the custom claim
226+
* @return this {@link TokenPayload} instance for method chaining
227+
* @throws IllegalStateException if the claim name is a registered claim
228+
*/
99229
public TokenPayload withClaim(String name, String value) {
100230
if (RegisteredClaims.VALUES.contains(name)) {
101231
throw new IllegalStateException("Please set registered claims with pre-defined methods");
@@ -105,10 +235,26 @@ public TokenPayload withClaim(String name, String value) {
105235
return this;
106236
}
107237

238+
/**
239+
* Checks if the JWT payload has a valid issuer.
240+
* <p>
241+
* Returns {@code true} if the issuer is non-null and not blank, indicating that an issuer has
242+
* been set.
243+
*
244+
* @return {@code true} if an issuer is set, {@code false} otherwise
245+
*/
108246
public boolean hasIssuer() {
109247
return Objects.nonNull(issuer) && !issuer.isBlank();
110248
}
111249

250+
/**
251+
* Retrieves the complete JWT payload as a map.
252+
* <p>
253+
* Constructs a map containing all custom claims, registered claims (if set), and audiences.
254+
* Only non-empty or non-blank values are included to ensure a clean payload.
255+
*
256+
* @return a map containing the JWT payload
257+
*/
112258
public Map<String, Object> getPayload() {
113259
var _payload = new HashMap<>(payload);
114260

@@ -128,7 +274,7 @@ public Map<String, Object> getPayload() {
128274
.ifPresent((jti) -> _payload.put(RegisteredClaims.TOKEN_ID, jti));
129275

130276
Optional.ofNullable(issuer)
131-
.map((iss) -> !iss.isBlank())
277+
.filter((iss) -> !iss.isBlank())
132278
.ifPresent((iss) -> _payload.put(RegisteredClaims.ISSUER, iss));
133279

134280
Optional.ofNullable(issuedAt)
@@ -139,5 +285,4 @@ public Map<String, Object> getPayload() {
139285

140286
return _payload;
141287
}
142-
143288
}

simple-jwt/src/main/java/com/onixbyte/jwt/TokenResolver.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,23 @@
2323
import java.util.Map;
2424

2525
/**
26+
* Interface for resolving and verifying JSON Web Tokens (JWTs).
27+
* <p>
28+
* Defines a contract for implementations that parse, verify, and extract components from JWTs.
29+
* Provides methods to validate the token's signature, retrieve its header and payload, and split it
30+
* into raw components. Implementations are expected to handle cryptographic verification and JSON
31+
* deserialisation specific to their signing algorithm.
2632
*
33+
* @author zihluwang
2734
*/
2835
public interface TokenResolver {
2936

3037
/**
31-
* Verifies the HMAC signature of the provided JWT.
38+
* Verifies the signature of the provided JWT.
3239
* <p>
33-
* Splits the token into its components and uses the configured algorithm and secret to check
34-
* the signature's validity. If the signature does not match, an exception is thrown by the
35-
* underlying cryptographic utility.
40+
* Splits the token into its components and checks the signature's validity using the
41+
* implementation's configured algorithm and key. If the signature does not match, an exception
42+
* is thrown.
3643
*
3744
* @param token the JWT string to verify
3845
* @throws IllegalArgumentException if the token is malformed or the signature verification
@@ -68,6 +75,9 @@ public interface TokenResolver {
6875

6976
/**
7077
* Splits a JWT into its raw components: header, payload, and signature.
78+
* <p>
79+
* Provides a default implementation that separates the token string into its three parts using
80+
* dot separators and returns them as a {@link RawTokenComponent}.
7181
*
7282
* @param token the JWT string to split
7383
* @return a {@link RawTokenComponent} containing the header, payload, and signature as strings

0 commit comments

Comments
 (0)