37public final class TokenSpec {
41 private TokenSpec(
final Builder
builder) {
42 final Instant issuedAt = builder.issuedAt ==
null ? Instant.now() :
builder.issuedAt;
43 final Instant expiresAt = resolveExpiresAt(issuedAt,
builder.expiresAt,
builder.ttl);
46 throw new IllegalArgumentException(
"subject is required");
48 if (expiresAt ==
null) {
49 throw new IllegalArgumentException(
"expiresAt or ttl is required");
59 .jwtId(
builder.jwtId ==
null ||
builder.jwtId.isBlank() ? UUID.randomUUID().toString() :
builder.jwtId)
75 private static Instant resolveExpiresAt(
final Instant issuedAt,
final Instant expiresAt,
final Duration ttl) {
76 if (expiresAt !=
null) {
80 if (ttl.isNegative() || ttl.isZero()) {
81 throw new IllegalArgumentException(
"ttl must be > 0");
83 return issuedAt.plus(ttl);
88 public static final class Builder {
89 private String subject;
90 private String issuer;
91 private String[] audience;
92 private Instant issuedAt;
93 private Instant expiresAt;
95 private Instant notBefore;
97 private String[] roles;
98 private TokenType tokenType;
99 private String clientId;
100 private Map<String, Object> customClaims =
new LinkedHashMap<>();
105 public Builder subject(
final String subject) {
106 this.subject = subject;
110 public Builder issuer(
final String issuer) {
111 this.issuer = issuer;
115 public Builder audience(
final String... audience) {
116 this.audience = audience ==
null ?
new String[0] : audience;
120 public Builder issuedAt(
final Instant issuedAt) {
121 this.issuedAt = issuedAt;
125 public Builder expiresAt(
final Instant expiresAt) {
126 this.expiresAt = expiresAt;
130 public Builder ttl(
final Duration ttl) {
135 public Builder notBefore(
final Instant notBefore) {
136 this.notBefore = notBefore;
140 public Builder jwtId(
final String jwtId) {
145 public Builder roles(
final String... roles) {
146 this.roles = roles ==
null ?
new String[0] : roles;
150 public Builder tokenType(
final TokenType tokenType) {
151 this.tokenType = tokenType;
155 public Builder clientId(
final String clientId) {
156 this.clientId = clientId;
160 public Builder claim(
final String key,
final Object value) {
161 if (key ==
null || key.isBlank()) {
162 throw new IllegalArgumentException(
"claim key is required");
164 customClaims.put(key, value);
168 public Builder
claims(
final Map<String, Object> claims) {
169 customClaims = claims ==
null ?
new LinkedHashMap<>() : new LinkedHashMap<>(claims);
173 public TokenSpec build() {
174 return new TokenSpec(
this);