Skip to content

Commit

Permalink
KEYCLOAK-1937
Browse files Browse the repository at this point in the history
OpenID Connect Dynamic Client Registration

KEYCLOAK-1938
Register clients from SAML Entity Descriptors
  • Loading branch information
stianst committed Nov 24, 2015
1 parent d2ba466 commit 4f2b97d
Show file tree
Hide file tree
Showing 25 changed files with 817 additions and 483 deletions.
Expand Up @@ -5,6 +5,7 @@
import org.keycloak.common.util.Base64;
import org.keycloak.representations.idm.ClientInitialAccessPresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;

/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
Expand All @@ -21,11 +22,14 @@ public static Auth token(ClientInitialAccessPresentation initialAccess) {
return new BearerTokenAuth(initialAccess.getToken());
}


public static Auth token(ClientRepresentation client) {
return new BearerTokenAuth(client.getRegistrationAccessToken());
}

public static Auth token(OIDCClientRepresentation client) {
return new BearerTokenAuth(client.getRegistrationAccessToken());
}

public static Auth client(String clientId, String clientSecret) {
return new BasicAuth(clientId, clientSecret);
}
Expand Down
Expand Up @@ -3,8 +3,10 @@
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
import org.keycloak.util.JsonSerialization;

import java.io.IOException;
Expand All @@ -18,10 +20,17 @@ public class ClientRegistration {
public static final ObjectMapper outputMapper = new ObjectMapper();
static {
outputMapper.getSerializationConfig().addMixInAnnotations(ClientRepresentation.class, ClientRepresentationMixIn.class);
outputMapper.getSerializationConfig().addMixInAnnotations(OIDCClientRepresentation.class, OIDCClientRepresentationMixIn.class);
outputMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
}

private final String JSON = "application/json";
private final String XML = "application/xml";

private final String DEFAULT = "default";
private final String INSTALLATION = "install";
private final String OIDC = "openid-connect";
private final String SAML = "saml2-entity-descriptor";

private HttpUtil httpUtil;

Expand All @@ -47,23 +56,23 @@ public ClientRegistration auth(Auth auth) {

public ClientRepresentation create(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = httpUtil.doPost(content, DEFAULT);
InputStream resultStream = httpUtil.doPost(content, JSON, JSON, DEFAULT);
return deserialize(resultStream, ClientRepresentation.class);
}

public ClientRepresentation get(String clientId) throws ClientRegistrationException {
InputStream resultStream = httpUtil.doGet(DEFAULT, clientId);
InputStream resultStream = httpUtil.doGet(JSON, DEFAULT, clientId);
return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
}

public AdapterConfig getAdapterConfig(String clientId) throws ClientRegistrationException {
InputStream resultStream = httpUtil.doGet(INSTALLATION, clientId);
InputStream resultStream = httpUtil.doGet(JSON, INSTALLATION, clientId);
return resultStream != null ? deserialize(resultStream, AdapterConfig.class) : null;
}

public ClientRepresentation update(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = httpUtil.doPut(content, DEFAULT, client.getClientId());
InputStream resultStream = httpUtil.doPut(content, JSON, JSON, DEFAULT, client.getClientId());
return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
}

Expand All @@ -75,10 +84,17 @@ public void delete(String clientId) throws ClientRegistrationException {
httpUtil.doDelete(DEFAULT, clientId);
}

public static String serialize(ClientRepresentation client) throws ClientRegistrationException {
try {
public OIDCClientRegistration oidc() {
return new OIDCClientRegistration();
}

return outputMapper.writeValueAsString(client);
public SAMLClientRegistration saml() {
return new SAMLClientRegistration();
}

public static String serialize(Object obj) throws ClientRegistrationException {
try {
return outputMapper.writeValueAsString(obj);
} catch (IOException e) {
throw new ClientRegistrationException("Failed to write json object", e);
}
Expand All @@ -92,6 +108,44 @@ private static <T> T deserialize(InputStream inputStream, Class<T> clazz) throws
}
}

public class OIDCClientRegistration {

public OIDCClientRepresentation create(OIDCClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = httpUtil.doPost(content, JSON, JSON, OIDC);
return deserialize(resultStream, OIDCClientRepresentation.class);
}

public OIDCClientRepresentation get(String clientId) throws ClientRegistrationException {
InputStream resultStream = httpUtil.doGet(JSON, OIDC, clientId);
return resultStream != null ? deserialize(resultStream, OIDCClientRepresentation.class) : null;
}

public OIDCClientRepresentation update(OIDCClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = httpUtil.doPut(content, JSON, JSON, OIDC, client.getClientId());
return resultStream != null ? deserialize(resultStream, OIDCClientRepresentation.class) : null;
}

public void delete(OIDCClientRepresentation client) throws ClientRegistrationException {
delete(client.getClientId());
}

public void delete(String clientId) throws ClientRegistrationException {
httpUtil.doDelete(OIDC, clientId);
}

}

public class SAMLClientRegistration {

public ClientRepresentation create(String entityDescriptor) throws ClientRegistrationException {
InputStream resultStream = httpUtil.doPost(entityDescriptor, XML, JSON, SAML);
return deserialize(resultStream, ClientRepresentation.class);
}

}

public static class ClientRegistrationBuilder {

private String url;
Expand Down
Expand Up @@ -33,12 +33,12 @@ void setAuth(Auth auth) {
this.auth = auth;
}

InputStream doPost(String content, String... path) throws ClientRegistrationException {
InputStream doPost(String content, String contentType, String acceptType, String... path) throws ClientRegistrationException {
try {
HttpPost request = new HttpPost(getUrl(baseUri, path));

request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
request.setHeader(HttpHeaders.ACCEPT, acceptType);
request.setEntity(new StringEntity(content));

addAuth(request);
Expand All @@ -60,11 +60,11 @@ InputStream doPost(String content, String... path) throws ClientRegistrationExce
}
}

InputStream doGet(String... path) throws ClientRegistrationException {
InputStream doGet(String acceptType, String... path) throws ClientRegistrationException {
try {
HttpGet request = new HttpGet(getUrl(baseUri, path));

request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setHeader(HttpHeaders.ACCEPT, acceptType);

addAuth(request);

Expand All @@ -90,12 +90,12 @@ InputStream doGet(String... path) throws ClientRegistrationException {
}
}

InputStream doPut(String content, String... path) throws ClientRegistrationException {
InputStream doPut(String content, String contentType, String acceptType, String... path) throws ClientRegistrationException {
try {
HttpPut request = new HttpPut(getUrl(baseUri, path));

request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
request.setHeader(HttpHeaders.ACCEPT, acceptType);
request.setEntity(new StringEntity(content));

addAuth(request);
Expand Down Expand Up @@ -134,7 +134,7 @@ void doDelete(String... path) throws ClientRegistrationException {
response.getEntity().getContent().close();
}

if (response.getStatusLine().getStatusCode() != 200) {
if (response.getStatusLine().getStatusCode() != 204) {
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
Expand Down
@@ -0,0 +1,22 @@
package org.keycloak.client.registration;

import org.codehaus.jackson.annotate.JsonIgnore;

/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
abstract class OIDCClientRepresentationMixIn {

@JsonIgnore
private Integer client_id_issued_at;

@JsonIgnore
private Integer client_secret_expires_at;

@JsonIgnore
private String registration_client_uri;

@JsonIgnore
private String registration_access_token;

}
Expand Up @@ -62,6 +62,8 @@ public static void main(String[] args) throws CommandLineParserException, Comman
CommandContainer command = registry.getCommand(args[0], null);
ParserGenerator.parseAndPopulate(command, args[0], Arrays.copyOfRange(args, 1, args.length));
}*/

//commandInvocation.getCommandRegistry().getAllCommandNames()
}

}
Expand Down

0 comments on commit 4f2b97d

Please sign in to comment.