/
JsonWebTokenSigner.java
101 lines (87 loc) · 2.93 KB
/
JsonWebTokenSigner.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package org.apereo.cas.util.jwt;
import org.apereo.cas.util.EncodingUtils;
import lombok.Builder;
import lombok.experimental.SuperBuilder;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang3.ArrayUtils;
import org.jooq.lambda.Unchecked;
import org.jose4j.jwa.AlgorithmConstraints;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* This is {@link JsonWebTokenSigner}.
*
* @author Misagh Moayyed
* @since 6.6.0
*/
@SuperBuilder
@Slf4j
public class JsonWebTokenSigner {
/**
* Allow all algorithms except none.
*/
public static final Set<String> ALGORITHM_ALL_EXCEPT_NONE = Set.of("*");
@Builder.Default
private final String keyId = UUID.randomUUID().toString();
private final String algorithm;
@Builder.Default
private final Map<String, Object> headers = new LinkedHashMap<>();
private final Key key;
@Builder.Default
private final Set<String> allowedAlgorithms = new LinkedHashSet<>();
/**
* Sign byte array.
*
* @param value the value
* @return the byte []
*/
public byte[] sign(final byte[] value) {
return Unchecked.supplier(() -> {
val base64 = EncodingUtils.encodeUrlSafeBase64(value);
return sign(base64, true).getBytes(StandardCharsets.UTF_8);
}).get();
}
/**
* Sign claims.
*
* @param claims the claims
* @return the string
*/
public String sign(final JwtClaims claims) {
return Unchecked.supplier(() -> {
val jsonClaims = claims.toJson();
return sign(jsonClaims, false);
}).get();
}
private String sign(final String payload, final boolean encoded) throws Exception {
val jws = new JsonWebSignature();
if (encoded) {
jws.setEncodedPayload(payload);
} else {
jws.setPayload(payload);
}
jws.setAlgorithmHeaderValue(this.algorithm);
jws.setAlgorithmConstraints(getAlgorithmConstraints());
jws.setHeader("typ", "JWT");
jws.setKey(key);
jws.setKeyIdHeaderValue(this.keyId);
headers.forEach((k, v) -> jws.setHeader(k, v.toString()));
LOGGER.trace("Signing id token with key id header value [{}] and algorithm header value [{}]",
jws.getKeyIdHeaderValue(), jws.getAlgorithmHeaderValue());
return jws.getCompactSerialization();
}
private AlgorithmConstraints getAlgorithmConstraints() {
return allowedAlgorithms.isEmpty() || allowedAlgorithms.contains("*")
? AlgorithmConstraints.DISALLOW_NONE
: new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.PERMIT,
allowedAlgorithms.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
}
}