Ether Framework
Unified API docs for Ether modules
Loading...
Searching...
No Matches
TokenClaims.java
Go to the documentation of this file.
1package dev.rafex.ether.jwt;
2
3/*-
4 * #%L
5 * ether-jwt
6 * %%
7 * Copyright (C) 2025 - 2026 Raúl Eduardo González Argote
8 * %%
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 * #L%
27 */
28
29import java.time.Instant;
30import java.util.ArrayList;
31import java.util.Collections;
32import java.util.LinkedHashMap;
33import java.util.List;
34import java.util.Map;
35
36/** Normalized claims extracted from a JWT token. */
37public final class TokenClaims {
38
39 private final String subject;
40 private final String issuer;
41 private final List<String> audience;
42 private final Instant expiresAt;
43 private final Instant issuedAt;
44 private final Instant notBefore;
45 private final String jwtId;
46 private final List<String> roles;
47 private final TokenType tokenType;
48 private final String clientId;
49 private final Map<String, Object> extras;
50
51 private TokenClaims(final Builder builder) {
52 this.subject = builder.subject;
53 this.issuer = builder.issuer;
54 this.audience = immutableList(builder.audience);
55 this.expiresAt = builder.expiresAt;
56 this.issuedAt = builder.issuedAt;
57 this.notBefore = builder.notBefore;
58 this.jwtId = builder.jwtId;
59 this.roles = immutableList(builder.roles);
60 this.tokenType = builder.tokenType;
61 this.clientId = builder.clientId;
62 this.extras = Collections.unmodifiableMap(new LinkedHashMap<>(builder.extras));
63 }
64
65 public static Builder builder() {
66 return new Builder();
67 }
68
69 public String subject() {
70 return subject;
71 }
72
73 public String issuer() {
74 return issuer;
75 }
76
77 public List<String> audience() {
78 return audience;
79 }
80
81 public Instant expiresAt() {
82 return expiresAt;
83 }
84
85 public Instant issuedAt() {
86 return issuedAt;
87 }
88
89 public Instant notBefore() {
90 return notBefore;
91 }
92
93 public String jwtId() {
94 return jwtId;
95 }
96
97 public List<String> roles() {
98 return roles;
99 }
100
102 return tokenType;
103 }
104
105 public String clientId() {
106 return clientId;
107 }
108
109 public Map<String, Object> extras() {
110 return extras;
111 }
112
113 public Builder toBuilder() {
114 return builder().subject(subject).issuer(issuer).audience(audience).expiresAt(expiresAt).issuedAt(issuedAt)
115 .notBefore(notBefore).jwtId(jwtId).roles(roles).tokenType(tokenType).clientId(clientId).extras(extras);
116 }
117
118 private static List<String> immutableList(final List<String> input) {
119 if (input == null || input.isEmpty()) {
120 return List.of();
121 }
122 final List<String> values = new ArrayList<>();
123 for (final String value : input) {
124 if (value != null && !value.isBlank()) {
125 values.add(value);
126 }
127 }
128 return Collections.unmodifiableList(values);
129 }
130
131 public static final class Builder {
132 private String subject;
133 private String issuer;
134 private List<String> audience = new ArrayList<>();
135 private Instant expiresAt;
136 private Instant issuedAt;
137 private Instant notBefore;
138 private String jwtId;
139 private List<String> roles = new ArrayList<>();
140 private TokenType tokenType;
141 private String clientId;
142 private Map<String, Object> extras = new LinkedHashMap<>();
143
144 private Builder() {
145 }
146
147 public Builder subject(final String subject) {
148 this.subject = blankToNull(subject);
149 return this;
150 }
151
152 public Builder issuer(final String issuer) {
153 this.issuer = blankToNull(issuer);
154 return this;
155 }
156
157 public Builder audience(final List<String> audience) {
158 this.audience = audience == null ? new ArrayList<>() : new ArrayList<>(audience);
159 return this;
160 }
161
162 public Builder audience(final String... audience) {
163 final List<String> values = new ArrayList<>();
164 if (audience != null) {
165 Collections.addAll(values, audience);
166 }
167 this.audience = values;
168 return this;
169 }
170
171 public Builder expiresAt(final Instant expiresAt) {
172 this.expiresAt = expiresAt;
173 return this;
174 }
175
176 public Builder issuedAt(final Instant issuedAt) {
177 this.issuedAt = issuedAt;
178 return this;
179 }
180
181 public Builder notBefore(final Instant notBefore) {
182 this.notBefore = notBefore;
183 return this;
184 }
185
186 public Builder jwtId(final String jwtId) {
187 this.jwtId = blankToNull(jwtId);
188 return this;
189 }
190
191 public Builder roles(final List<String> roles) {
192 this.roles = roles == null ? new ArrayList<>() : new ArrayList<>(roles);
193 return this;
194 }
195
196 public Builder roles(final String... roles) {
197 final List<String> values = new ArrayList<>();
198 if (roles != null) {
199 Collections.addAll(values, roles);
200 }
201 this.roles = values;
202 return this;
203 }
204
205 public Builder tokenType(final TokenType tokenType) {
206 this.tokenType = tokenType;
207 return this;
208 }
209
210 public Builder clientId(final String clientId) {
211 this.clientId = blankToNull(clientId);
212 return this;
213 }
214
215 public Builder extras(final Map<String, Object> extras) {
216 this.extras = extras == null ? new LinkedHashMap<>() : new LinkedHashMap<>(extras);
217 return this;
218 }
219
220 public Builder extra(final String key, final Object value) {
221 if (key == null || key.isBlank()) {
222 throw new IllegalArgumentException("extra claim key is required");
223 }
224 extras.put(key, value);
225 return this;
226 }
227
228 public TokenClaims build() {
229 return new TokenClaims(this);
230 }
231
232 private static String blankToNull(final String value) {
233 return value == null || value.isBlank() ? null : value;
234 }
235 }
236}
Map< String, Object > extras()
Supported business token types.