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.common.util.Base64;
import org.keycloak.representations.idm.ClientInitialAccessPresentation; import org.keycloak.representations.idm.ClientInitialAccessPresentation;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;


/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @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()); return new BearerTokenAuth(initialAccess.getToken());
} }



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


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

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


import java.io.IOException; import java.io.IOException;
Expand All @@ -18,10 +20,17 @@ public class ClientRegistration {
public static final ObjectMapper outputMapper = new ObjectMapper(); public static final ObjectMapper outputMapper = new ObjectMapper();
static { static {
outputMapper.getSerializationConfig().addMixInAnnotations(ClientRepresentation.class, ClientRepresentationMixIn.class); 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 DEFAULT = "default";
private final String INSTALLATION = "install"; private final String INSTALLATION = "install";
private final String OIDC = "openid-connect";
private final String SAML = "saml2-entity-descriptor";


private HttpUtil httpUtil; private HttpUtil httpUtil;


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


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


public ClientRepresentation get(String clientId) throws ClientRegistrationException { 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; return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
} }


public AdapterConfig getAdapterConfig(String clientId) throws ClientRegistrationException { 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; return resultStream != null ? deserialize(resultStream, AdapterConfig.class) : null;
} }


public ClientRepresentation update(ClientRepresentation client) throws ClientRegistrationException { public ClientRepresentation update(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client); 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; 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); httpUtil.doDelete(DEFAULT, clientId);
} }


public static String serialize(ClientRepresentation client) throws ClientRegistrationException { public OIDCClientRegistration oidc() {
try { 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) { } catch (IOException e) {
throw new ClientRegistrationException("Failed to write json object", 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 { public static class ClientRegistrationBuilder {


private String url; private String url;
Expand Down
Expand Up @@ -33,12 +33,12 @@ void setAuth(Auth auth) {
this.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 { try {
HttpPost request = new HttpPost(getUrl(baseUri, path)); HttpPost request = new HttpPost(getUrl(baseUri, path));


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


addAuth(request); 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 { try {
HttpGet request = new HttpGet(getUrl(baseUri, path)); HttpGet request = new HttpGet(getUrl(baseUri, path));


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


addAuth(request); 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 { try {
HttpPut request = new HttpPut(getUrl(baseUri, path)); HttpPut request = new HttpPut(getUrl(baseUri, path));


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


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


if (response.getStatusLine().getStatusCode() != 200) { if (response.getStatusLine().getStatusCode() != 204) {
throw new HttpErrorException(response.getStatusLine()); throw new HttpErrorException(response.getStatusLine());
} }
} catch (IOException e) { } 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); CommandContainer command = registry.getCommand(args[0], null);
ParserGenerator.parseAndPopulate(command, args[0], Arrays.copyOfRange(args, 1, args.length)); 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.