Introduce mechanism for different trust material sources (#48869)

closes #48269



Signed-off-by: Dominik Schlosser <dominik.schlosser@gmail.com>
Signed-off-by: mposolda <mposolda@gmail.com>
Co-authored-by: mposolda <mposolda@gmail.com>
This commit is contained in:
Dominik Schlosser
2026-05-25 08:12:28 +02:00
committed by GitHub
parent 94dcc24a8d
commit a1bd1ab855
18 changed files with 907 additions and 106 deletions
@@ -0,0 +1,33 @@
/*
* Copyright 2026 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
import java.util.stream.Stream;
import org.keycloak.jose.jwk.JWK;
import org.keycloak.models.IdentityProviderModel;
/**
* Identity providers that expose reusable trust material for flows such as
* client attestation or OID4VCI key attestation.
*/
public interface TrustMaterialIdentityProvider<C extends IdentityProviderModel> extends IdentityProvider<C> {
Stream<JWK> resolveKeys(TrustMaterialRequest request);
}
@@ -0,0 +1,73 @@
/*
* Copyright 2026 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.broker.provider;
public class TrustMaterialRequest {
private final String kid;
private final String algorithm;
private final String issuer;
private TrustMaterialRequest(Builder builder) {
this.kid = builder.kid;
this.algorithm = builder.algorithm;
this.issuer = builder.issuer;
}
public String getKid() {
return kid;
}
public String getAlgorithm() {
return algorithm;
}
public String getIssuer() {
return issuer;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String kid;
private String algorithm;
private String issuer;
public Builder kid(String kid) {
this.kid = kid;
return this;
}
public Builder algorithm(String algorithm) {
this.algorithm = algorithm;
return this;
}
public Builder issuer(String issuer) {
this.issuer = issuer;
return this;
}
public TrustMaterialRequest build() {
return new TrustMaterialRequest(this);
}
}
}
@@ -10,6 +10,7 @@ import org.keycloak.broker.provider.ClientAssertionIdentityProvider;
import org.keycloak.broker.provider.ExchangeExternalToken;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.JWTAuthorizationGrantProvider;
import org.keycloak.broker.provider.TrustMaterialIdentityProvider;
import org.keycloak.broker.provider.UserAuthenticationIdentityProvider;
import org.keycloak.broker.social.SocialIdentityProvider;
import org.keycloak.models.IdentityProviderCapability;
@@ -80,6 +81,7 @@ public class IdentityProviderTypeUtil {
return switch (type) {
case USER_AUTHENTICATION -> UserAuthenticationIdentityProvider.class;
case CLIENT_ASSERTION -> ClientAssertionIdentityProvider.class;
case TRUST_MATERIAL -> TrustMaterialIdentityProvider.class;
case EXCHANGE_EXTERNAL_TOKEN -> ExchangeExternalToken.class;
case JWT_AUTHORIZATION_GRANT -> JWTAuthorizationGrantProvider.class;
case ANY -> IdentityProvider.class;