Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -196,34 +196,6 @@ protected void logoutFromConsumerRealm() {
AccountHelper.logout(getConsumerRealm().admin(), getUserLogin());
}

// Turns off the first-broker-login review-profile step for flows that want to test something else
// without the review-profile page interrupting the redirect back to the consumer. Disabling the flow
// execution alone isn't enough: the new-testsuite consumer realm enables the VERIFY_PROFILE required
// action by default, which would still intercept the incomplete imported user (the provider user has
// no first/last name on purpose), so that is disabled too, mirroring the legacy suite (which never
// enabled VERIFY_PROFILE at all).
protected void disableUpdateProfileOnFirstLogin() {
var flows = getConsumerRealm().admin().flows();
for (AuthenticationExecutionInfoRepresentation execution :
flows.getExecutions(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW)) {
if (IdpCreateUserIfUniqueAuthenticatorFactory.PROVIDER_ID.equals(execution.getProviderId())) {
execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE.name());
flows.updateExecutions(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW, execution);
} else if (execution.getAlias() != null
&& execution.getAlias().equals(DefaultAuthenticationFlows.IDP_REVIEW_PROFILE_CONFIG_ALIAS)) {
AuthenticatorConfigRepresentation config = flows.getAuthenticatorConfig(execution.getAuthenticationConfig());
config.getConfig().put("update.profile.on.first.login", IdentityProviderRepresentation.UPFLM_OFF);
flows.updateAuthenticatorConfig(config.getId(), config);
}
}
for (RequiredActionProviderRepresentation action : getConsumerRealm().admin().flows().getRequiredActions()) {
if (UserModel.RequiredAction.VERIFY_PROFILE.name().equals(action.getAlias())) {
action.setEnabled(false);
getConsumerRealm().admin().flows().updateRequiredAction(action.getAlias(), action);
}
}
}

protected void assertNumFederatedIdentities(String username, int expected) {
ManagedRealm consumerRealm = getConsumerRealm();
List<UserRepresentation> users = consumerRealm.admin().users().search(username, true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.keycloak.tests.broker.oidc;

import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.tests.broker.AbstractKcOidcBrokerTest;
import org.keycloak.tests.common.CustomProvidersServerConfig;

import org.junit.jupiter.api.BeforeEach;

@KeycloakIntegrationTest(config = CustomProvidersServerConfig.class)
public class KcOidcBrokerIdpPublicKeyMissingUseTest extends AbstractKcOidcBrokerTest {

@BeforeEach
void configureMissingUseJwks() {
IdentityProviderRepresentation idp = consumerRealm.admin()
.identityProviders().get(getIdpAlias()).toRepresentation();
idp.getConfig().put("clientAuthMethod", OIDCLoginProtocol.CLIENT_SECRET_BASIC);
idp.getConfig().put(OIDCIdentityProviderConfig.JWKS_URL,
providerRealm.getBaseUrl() + "/missing-use-jwks/jwks");
consumerRealm.admin().identityProviders().get(getIdpAlias()).update(idp);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package org.keycloak.tests.providers.broker.oidc;

import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

import org.keycloak.crypto.KeyType;
import org.keycloak.jose.jwk.JSONWebKeySet;
import org.keycloak.jose.jwk.JWK;
import org.keycloak.jose.jwk.JWKBuilder;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resource.RealmResourceProvider;

public class MissingUseJwksRealmResourceProvider implements RealmResourceProvider {

private final KeycloakSession session;

public MissingUseJwksRealmResourceProvider(KeycloakSession session) {
this.session = session;
}

@Override
public Object getResource() {
return this;
}

@GET
@Path("jwks")
@Produces(MediaType.APPLICATION_JSON)
public Response jwks() {
RealmModel realm = session.getContext().getRealm();
JWK[] jwks = session.keys().getKeysStream(realm)
.filter(k -> k.getStatus().isEnabled() && k.getPublicKey() != null)
.map(k -> {
JWKBuilder b = JWKBuilder.create().kid(k.getKid()).algorithm(k.getAlgorithmOrDefault());
List<X509Certificate> certificates = Optional.ofNullable(k.getCertificateChain())
.filter(certs -> !certs.isEmpty())
.orElseGet(() -> Collections.singletonList(k.getCertificate()));
if (k.getType().equals(KeyType.RSA)) {
JWK rsaKey = b.rsa(k.getPublicKey(), certificates, k.getUse());
rsaKey.setPublicKeyUse(null);
return rsaKey;
} else if (k.getType().equals(KeyType.EC)) {
JWK ecKey = b.ec(k.getPublicKey(), k.getUse());
ecKey.setPublicKeyUse(null);
return ecKey;
} else if (k.getType().equals(KeyType.OKP)) {
JWK okpKey = b.okp(k.getPublicKey(), k.getUse());
okpKey.setPublicKeyUse(null);
return okpKey;
}
return null;
})
.filter(Objects::nonNull)
.toArray(JWK[]::new);

JSONWebKeySet keySet = new JSONWebKeySet();
keySet.setKeys(jwks);

return Response.ok(keySet).build();
}

@Override
public void close() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.keycloak.tests.providers.broker.oidc;

import org.keycloak.Config.Scope;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.resource.RealmResourceProviderFactory;

public class MissingUseJwksRealmResourceProviderFactory implements RealmResourceProviderFactory {

public static final String ID = "missing-use-jwks";

@Override
public String getId() {
return ID;
}

@Override
public RealmResourceProvider create(KeycloakSession session) {
return new MissingUseJwksRealmResourceProvider(session);
}

@Override
public void init(Scope config) {
}

@Override
public void postInit(KeycloakSessionFactory factory) {
}

@Override
public void close() {
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
org.keycloak.tests.providers.rest.ErrorTestingRealmResourceProviderFactory
org.keycloak.tests.providers.rest.CookieTestingRealmResourceProviderFactory
org.keycloak.tests.providers.broker.oidc.MissingUseJwksRealmResourceProviderFactory

This file was deleted.

Loading