Skip to content
Open
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 @@ -228,7 +228,6 @@ public Response getVersionPreflight(final @PathParam("realm") String name,

@GET
@Path("{realm}/.well-known/{alias}")
@Produces({MediaType.APPLICATION_JSON, APPLICATION_JWT})
public Response getWellKnown(final @PathParam("realm") String realm,
final @PathParam("alias") String alias) {
return getWellKnownResponse(session, realm, alias, logger);
Expand All @@ -249,8 +248,12 @@ public static Response getWellKnownResponse(KeycloakSession session, String real
Object config = wellKnown.getConfig();
Response.ResponseBuilder responseBuilder;

// Check if the provider returned a JWT string or JSON object
responseBuilder = Response.ok(config).type(config instanceof String ? APPLICATION_JWT : MediaType.APPLICATION_JSON);
String mediaType = wellKnown.getMediaType();
if (mediaType == null) {
// Check if the provider returned a JWT string or JSON object
mediaType = config instanceof String ? APPLICATION_JWT : MediaType.APPLICATION_JSON;
}
responseBuilder = Response.ok(config).type(mediaType);

return Cors.builder().allowAllOrigins().auth().add(responseBuilder.cacheControl(CacheControlUtil.noCache()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ public Response getWellKnownPreflight(final @PathParam("provider") String alias,

@GET
@Path("{provider}/realms/{realm}")
@Produces({MediaType.APPLICATION_JSON, org.keycloak.utils.MediaType.APPLICATION_JWT})
public Response getWellKnown(final @PathParam("provider") String alias,
final @PathParam("realm") String realm) {
if (!isValidProvider(alias)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,15 @@ public interface WellKnownProvider extends Provider {

Object getConfig();

/**
* Media type of the response, for example {@code application/entity-statement+jwt}. It is called after {@link #getConfig()},
* so it may depend on the returned config.
*
* @return the media type, or {@code null} to use {@code application/jwt} if the config is a {@link String} and
* {@code application/json} otherwise
*/
default String getMediaType() {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.keycloak.tests.oidc;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

import org.keycloak.testframework.annotations.InjectKeycloakUrls;
import org.keycloak.testframework.annotations.InjectRealm;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.testframework.realm.ManagedRealm;
import org.keycloak.testframework.server.KeycloakServerConfig;
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.tests.providers.wellknown.TestMediaTypeWellKnownProvider;
import org.keycloak.tests.providers.wellknown.TestMediaTypeWellKnownProviderFactory;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

@KeycloakIntegrationTest(config = WellKnownMediaTypeTest.CustomProvidersServerConfig.class)
public class WellKnownMediaTypeTest {

@InjectRealm
ManagedRealm realm;

@InjectKeycloakUrls
KeycloakUrls keycloakUrls;

@Test
public void providerMediaType() throws Exception {
assertProviderMediaType(get(realmUrl(), "*/*"));
}

@Test
public void providerMediaTypeAccepted() throws Exception {
assertProviderMediaType(get(realmUrl(), TestMediaTypeWellKnownProvider.MEDIA_TYPE));
}

@Test
public void providerMediaTypeViaServerMetadata() throws Exception {
assertProviderMediaType(get(serverMetadataUrl(), "*/*"));
}

@Test
public void providerMediaTypeAcceptedViaServerMetadata() throws Exception {
assertProviderMediaType(get(serverMetadataUrl(), TestMediaTypeWellKnownProvider.MEDIA_TYPE));
}

@Test
public void defaultMediaTypeUnchanged() throws Exception {
String url = realm.getBaseUrl() + "/.well-known/openid-configuration";

for (String accept : new String[] { "*/*", "application/json" }) {
HttpResponse<String> response = get(url, accept);
assertEquals(200, response.statusCode());
assertEquals("application/json", response.headers().firstValue("Content-Type").orElse(null));
}
}

private String realmUrl() {
return realm.getBaseUrl() + "/.well-known/" + TestMediaTypeWellKnownProviderFactory.ID;
}

private String serverMetadataUrl() {
return keycloakUrls.getBaseUrl() + "/.well-known/" + TestMediaTypeWellKnownProviderFactory.ID + "/realms/" + realm.getName();
}

private void assertProviderMediaType(HttpResponse<String> response) {
assertEquals(200, response.statusCode());
assertEquals(TestMediaTypeWellKnownProvider.MEDIA_TYPE, response.headers().firstValue("Content-Type").orElse(null));
assertEquals(TestMediaTypeWellKnownProvider.CONFIG, response.body());
}

private HttpResponse<String> get(String url, String accept) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create(url)).header("Accept", accept).GET().build();
return HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
}

public static class CustomProvidersServerConfig implements KeycloakServerConfig {

@Override
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
return config.dependency("org.keycloak.tests", "keycloak-tests-custom-providers");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.keycloak.tests.providers.wellknown;

import org.keycloak.wellknown.WellKnownProvider;

public class TestMediaTypeWellKnownProvider implements WellKnownProvider {

public static final String CONFIG = "eyJhbGciOiJub25lIn0.eyJpc3MiOiJ0ZXN0In0.";
public static final String MEDIA_TYPE = "application/entity-statement+jwt";

@Override
public Object getConfig() {
return CONFIG;
}

@Override
public String getMediaType() {
return MEDIA_TYPE;
}

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

import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.wellknown.WellKnownProvider;
import org.keycloak.wellknown.WellKnownProviderFactory;

public class TestMediaTypeWellKnownProviderFactory implements WellKnownProviderFactory {

public static final String ID = "test-media-type";

@Override
public WellKnownProvider create(KeycloakSession session) {
return new TestMediaTypeWellKnownProvider();
}

@Override
public void init(Config.Scope config) {
}

@Override
public void postInit(KeycloakSessionFactory factory) {
}

@Override
public void close() {
}

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

@Override
public boolean isAvailableViaServerMetadata() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.keycloak.tests.providers.wellknown.TestMediaTypeWellKnownProviderFactory
Loading