use of io.helidon.security.jwt.jwk.Jwk in project helidon by oracle.
the class SignedJwtTest method testSignatureNone.
@Test
public void testSignatureNone() {
Jwt jwt = Jwt.builder().algorithm("none").issuer("unit-test").build();
Jwk defaultJwk = Jwk.NONE_JWK;
SignedJwt signed = SignedJwt.sign(jwt, customKeys);
assertThat(signed, notNullValue());
assertThat(signed.getSignature(), notNullValue());
assertThat(signed.getSignature(), is(new byte[0]));
Errors errors = signed.verifySignature(customKeys, defaultJwk);
assertThat(errors, notNullValue());
errors.log(LOGGER);
errors.checkValid();
}
use of io.helidon.security.jwt.jwk.Jwk in project helidon by oracle.
the class SignedJwt method verifySignature.
/**
* Verify signature against the provided keys (the kid of thisPrincipal
* JWT should be present in the {@link JwkKeys} provided).
*
* @param keys JwkKeys to obtain a key to verify signature
* @param defaultJwk Default value of JWK
* @return Errors with collected messages, see {@link Errors#isValid()} and {@link Errors#checkValid()}
*/
public Errors verifySignature(JwkKeys keys, Jwk defaultJwk) {
Errors.Collector collector = Errors.collector();
String alg = headers.algorithm().orElse(null);
String kid = headers.keyId().orElse(null);
Jwk jwk = null;
boolean jwtWithoutKidAndNoneAlg = false;
// TODO support multiple JWK under same kid if different alg (see if spec allows this)
if (null == alg) {
if (null == kid) {
if (defaultJwk == null) {
jwtWithoutKidAndNoneAlg = true;
jwk = Jwk.NONE_JWK;
} else {
jwk = defaultJwk;
}
alg = jwk.algorithm();
} else {
// null alg, non-null kid - will use alg of jwk
jwk = keys.forKeyId(kid).orElse(null);
if (null == jwk) {
if (null == defaultJwk) {
collector.fatal(keys, "Key for key id: " + kid + " not found");
} else {
jwk = defaultJwk;
}
}
if (null != jwk) {
alg = jwk.algorithm();
}
}
} else {
// alg not null
if (null == kid) {
if (Jwk.ALG_NONE.equals(alg)) {
if (null != defaultJwk) {
if (defaultJwk.algorithm().equals(alg)) {
// yes, we expect none algorithm
} else {
collector.fatal("Algorithm is " + alg + ", default jwk requires " + defaultJwk.algorithm());
}
} else {
jwk = Jwk.NONE_JWK;
jwtWithoutKidAndNoneAlg = true;
}
} else {
jwk = defaultJwk;
if (null == jwk) {
collector.fatal("Algorithm is " + alg + ", yet no kid is defined in JWT header, cannot validate");
}
}
} else {
// both not null
jwk = keys.forKeyId(kid).orElse(null);
if (null == jwk) {
if ((null != defaultJwk) && alg.equals(defaultJwk.algorithm())) {
jwk = defaultJwk;
}
if (null == jwk) {
collector.fatal(keys, "Key for key id: " + kid + " not found");
}
}
}
}
if (null == jwk) {
return collector.collect();
}
if (jwtWithoutKidAndNoneAlg) {
collector.fatal(jwk, "None algorithm not allowed, unless specified as the default JWK");
}
// now if jwk algorithm is none, alg may be
if (jwk.algorithm().equals(alg)) {
try {
if (!jwk.verifySignature(signedBytes, signature)) {
collector.fatal(jwk, "Signature of JWT token is not valid, based on alg: " + alg + ", kid: " + kid);
}
} catch (Exception e) {
collector.fatal(jwk, "Failed to verify signature due to an exception: " + e.getClass().getName() + ": " + e.getMessage());
}
} else {
collector.fatal(jwk, "Algorithm of JWK (" + jwk.algorithm() + ") does not match algorithm of this JWT (" + alg + ") for kid: " + kid);
}
return collector.collect();
}
use of io.helidon.security.jwt.jwk.Jwk in project helidon by oracle.
the class JwtProvider method impersonate.
private OutboundSecurityResponse impersonate(JwtOutboundTarget ot, String username) {
Map<String, List<String>> headers = new HashMap<>();
Jwk jwk = signKeys.forKeyId(ot.jwkKid).orElseThrow(() -> new JwtException("Signing JWK with kid: " + ot.jwkKid + " is not defined."));
Jwt.Builder builder = Jwt.builder();
builder.addPayloadClaim("name", username);
builder.subject(username).preferredUsername(username).issuer(issuer).algorithm(jwk.algorithm());
ot.update(builder);
Jwt jwt = builder.build();
SignedJwt signed = SignedJwt.sign(jwt, jwk);
ot.outboundHandler.header(headers, signed.tokenContent());
return OutboundSecurityResponse.withHeaders(headers);
}
use of io.helidon.security.jwt.jwk.Jwk in project helidon by oracle.
the class SignedJwtTest method testSingatureNoAlgNoKid.
@Test
public void testSingatureNoAlgNoKid() {
Jwt jwt = Jwt.builder().build();
Jwk defaultJwk = Jwk.NONE_JWK;
SignedJwt signed = SignedJwt.sign(jwt, customKeys);
assertThat(signed, notNullValue());
assertThat(signed.getSignature(), notNullValue());
assertThat(signed.getSignature(), is(new byte[0]));
Errors errors = signed.verifySignature(customKeys, defaultJwk);
assertThat(errors, notNullValue());
errors.log(LOGGER);
errors.checkValid();
}
use of io.helidon.security.jwt.jwk.Jwk in project helidon by oracle.
the class JwtProvider method propagate.
private OutboundSecurityResponse propagate(JwtOutboundTarget ot, Subject subject) {
Map<String, List<String>> headers = new HashMap<>();
Jwk jwk = signKeys.forKeyId(ot.jwkKid).orElseThrow(() -> new JwtException("Signing JWK with kid: " + ot.jwkKid + " is not defined."));
Principal principal = subject.principal();
Jwt.Builder builder = Jwt.builder();
principal.abacAttributeNames().forEach(name -> {
principal.abacAttribute(name).ifPresent(val -> builder.addPayloadClaim(name, val));
});
principal.abacAttribute("full_name").ifPresentOrElse(name -> builder.addPayloadClaim("name", name), () -> builder.removePayloadClaim("name"));
builder.subject(principal.id()).preferredUsername(principal.getName()).issuer(issuer).algorithm(jwk.algorithm());
ot.update(builder);
Jwt jwt = builder.build();
SignedJwt signed = SignedJwt.sign(jwt, jwk);
ot.outboundHandler.header(headers, signed.tokenContent());
return OutboundSecurityResponse.withHeaders(headers);
}
Aggregations