mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
Add support for spiffe_refresh_hint to Spiffe Identity Provider (#43242)
Closes #42806 Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
parent
9546fca45e
commit
ab7939f33a
@ -1,11 +1,10 @@
|
|||||||
package org.keycloak.broker.spiffe;
|
package org.keycloak.broker.spiffe;
|
||||||
|
|
||||||
import org.keycloak.crypto.PublicKeysWrapper;
|
import org.keycloak.crypto.PublicKeysWrapper;
|
||||||
import org.keycloak.jose.jwk.JSONWebKeySet;
|
import org.keycloak.http.simple.SimpleHttp;
|
||||||
import org.keycloak.jose.jwk.JWK;
|
import org.keycloak.jose.jwk.JWK;
|
||||||
import org.keycloak.keys.PublicKeyLoader;
|
import org.keycloak.keys.PublicKeyLoader;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.protocol.oidc.utils.JWKSHttpUtils;
|
|
||||||
import org.keycloak.util.JWKSUtils;
|
import org.keycloak.util.JWKSUtils;
|
||||||
|
|
||||||
public class SpiffeBundleEndpointLoader implements PublicKeyLoader {
|
public class SpiffeBundleEndpointLoader implements PublicKeyLoader {
|
||||||
@ -20,8 +19,9 @@ public class SpiffeBundleEndpointLoader implements PublicKeyLoader {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PublicKeysWrapper loadKeys() throws Exception {
|
public PublicKeysWrapper loadKeys() throws Exception {
|
||||||
JSONWebKeySet jwks = JWKSHttpUtils.sendJwksRequest(session, bundleEndpoint);
|
SpiffeJSONWebKeySet jwks = SimpleHttp.create(session).doGet(bundleEndpoint).asJson(SpiffeJSONWebKeySet.class);
|
||||||
return JWKSUtils.getKeyWrappersForUse(jwks, JWK.Use.JWT_SVID);
|
PublicKeysWrapper keysWrapper = JWKSUtils.getKeyWrappersForUse(jwks, JWK.Use.JWT_SVID);
|
||||||
|
return jwks.getSpiffeRefreshHint() == null ? keysWrapper : new PublicKeysWrapper(keysWrapper.getKeys(), jwks.getSpiffeRefreshHint());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
package org.keycloak.broker.spiffe;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.keycloak.jose.jwk.JSONWebKeySet;
|
||||||
|
|
||||||
|
public class SpiffeJSONWebKeySet extends JSONWebKeySet {
|
||||||
|
|
||||||
|
@JsonProperty("spiffe_refresh_hint")
|
||||||
|
private Long spiffeRefreshHint;
|
||||||
|
|
||||||
|
public Long getSpiffeRefreshHint() {
|
||||||
|
return spiffeRefreshHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpiffeRefreshHint(Long spiffeRefreshHint) {
|
||||||
|
this.spiffeRefreshHint = spiffeRefreshHint;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -31,6 +31,8 @@ public class OAuthIdentityProvider {
|
|||||||
private final OAuthIdentityProviderKeys keys;
|
private final OAuthIdentityProviderKeys keys;
|
||||||
private final OAuthIdentityProviderConfigBuilder.OAuthIdentityProviderConfiguration config;
|
private final OAuthIdentityProviderConfigBuilder.OAuthIdentityProviderConfiguration config;
|
||||||
|
|
||||||
|
private int keysRequestCount = 0;
|
||||||
|
|
||||||
public OAuthIdentityProvider(HttpServer httpServer, OAuthIdentityProviderConfigBuilder.OAuthIdentityProviderConfiguration config) {
|
public OAuthIdentityProvider(HttpServer httpServer, OAuthIdentityProviderConfigBuilder.OAuthIdentityProviderConfiguration config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
if (!CryptoIntegration.isInitialised()) {
|
if (!CryptoIntegration.isInitialised()) {
|
||||||
@ -55,6 +57,10 @@ public class OAuthIdentityProvider {
|
|||||||
return new OAuthIdentityProviderKeys(config);
|
return new OAuthIdentityProviderKeys(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getKeysRequestCount() {
|
||||||
|
return keysRequestCount;
|
||||||
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
httpServer.removeContext("/idp/jwks");
|
httpServer.removeContext("/idp/jwks");
|
||||||
}
|
}
|
||||||
@ -68,6 +74,8 @@ public class OAuthIdentityProvider {
|
|||||||
OutputStream outputStream = exchange.getResponseBody();
|
OutputStream outputStream = exchange.getResponseBody();
|
||||||
outputStream.write(keys.getJwksString().getBytes(StandardCharsets.UTF_8));
|
outputStream.write(keys.getJwksString().getBytes(StandardCharsets.UTF_8));
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
|
|
||||||
|
keysRequestCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package org.keycloak.tests.client.authentication.external;
|
package org.keycloak.tests.client.authentication.external;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.MethodOrderer;
|
import org.junit.jupiter.api.MethodOrderer;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
@ -20,6 +21,8 @@ import org.keycloak.testframework.oauth.annotations.InjectOAuthIdentityProvider;
|
|||||||
import org.keycloak.testframework.realm.ManagedRealm;
|
import org.keycloak.testframework.realm.ManagedRealm;
|
||||||
import org.keycloak.testframework.realm.RealmConfig;
|
import org.keycloak.testframework.realm.RealmConfig;
|
||||||
import org.keycloak.testframework.realm.RealmConfigBuilder;
|
import org.keycloak.testframework.realm.RealmConfigBuilder;
|
||||||
|
import org.keycloak.testframework.remote.timeoffset.InjectTimeOffSet;
|
||||||
|
import org.keycloak.testframework.remote.timeoffset.TimeOffSet;
|
||||||
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
|
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
|
||||||
import org.keycloak.testsuite.util.IdentityProviderBuilder;
|
import org.keycloak.testsuite.util.IdentityProviderBuilder;
|
||||||
|
|
||||||
@ -39,10 +42,27 @@ public class SpiffeClientAuthTest extends AbstractFederatedClientAuthTest {
|
|||||||
@InjectOAuthIdentityProvider(config = SpiffeIdpConfig.class)
|
@InjectOAuthIdentityProvider(config = SpiffeIdpConfig.class)
|
||||||
OAuthIdentityProvider identityProvider;
|
OAuthIdentityProvider identityProvider;
|
||||||
|
|
||||||
|
@InjectTimeOffSet
|
||||||
|
TimeOffSet timeOffSet;
|
||||||
|
|
||||||
public SpiffeClientAuthTest() {
|
public SpiffeClientAuthTest() {
|
||||||
super(null, INTERNAL_CLIENT_ID, EXTERNAL_CLIENT_ID);
|
super(null, INTERNAL_CLIENT_ID, EXTERNAL_CLIENT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKeysCached() {
|
||||||
|
int initialKeyRequests = identityProvider.getKeysRequestCount();
|
||||||
|
Assertions.assertTrue(doClientGrant(createDefaultToken()).isSuccess());
|
||||||
|
Assertions.assertTrue(doClientGrant(createDefaultToken()).isSuccess());
|
||||||
|
Assertions.assertEquals(initialKeyRequests + 1, identityProvider.getKeysRequestCount());
|
||||||
|
|
||||||
|
timeOffSet.set(350);
|
||||||
|
|
||||||
|
Assertions.assertTrue(doClientGrant(createDefaultToken()).isSuccess());
|
||||||
|
Assertions.assertTrue(doClientGrant(createDefaultToken()).isSuccess());
|
||||||
|
Assertions.assertEquals(initialKeyRequests + 2, identityProvider.getKeysRequestCount());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvalidTrustDomain() {
|
public void testInvalidTrustDomain() {
|
||||||
realm.updateIdentityProviderWithCleanup(IDP_ALIAS, rep -> {
|
realm.updateIdentityProviderWithCleanup(IDP_ALIAS, rep -> {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user