added client dynamic registration service, extracted clientdetails<->json processing into its own static class
parent
0b0e52b7a3
commit
fb859fc39a
|
@ -0,0 +1,97 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.mitre.openid.connect.client.service.impl;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
|
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
|
||||||
|
import org.mitre.openid.connect.client.service.ClientConfigurationService;
|
||||||
|
import org.mitre.openid.connect.config.ServerConfiguration;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||||
|
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jricher
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DynamicRegistrationClientConfigurationService implements ClientConfigurationService {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(DynamicServerConfigurationService.class);
|
||||||
|
|
||||||
|
private LoadingCache<ServerConfiguration, ClientDetailsEntity> clients;
|
||||||
|
|
||||||
|
private ClientDetailsEntity template;
|
||||||
|
|
||||||
|
public DynamicRegistrationClientConfigurationService() {
|
||||||
|
clients = CacheBuilder.newBuilder().build(new DynamicClientRegistrationLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientDetails getClientConfiguration(ServerConfiguration issuer) {
|
||||||
|
try {
|
||||||
|
return clients.get(issuer);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
logger.warn("Unable to get client configuration", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the template
|
||||||
|
*/
|
||||||
|
public ClientDetailsEntity getTemplate() {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param template the template to set
|
||||||
|
*/
|
||||||
|
public void setTemplate(ClientDetailsEntity template) {
|
||||||
|
this.template = template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DynamicClientRegistrationLoader extends CacheLoader<ServerConfiguration, ClientDetailsEntity> {
|
||||||
|
private HttpClient httpClient = new DefaultHttpClient();
|
||||||
|
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||||
|
private JsonParser parser = new JsonParser();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientDetailsEntity load(ServerConfiguration serverConfig) throws Exception {
|
||||||
|
RestTemplate restTemplate = new RestTemplate(httpFactory);
|
||||||
|
|
||||||
|
// dynamically register this client
|
||||||
|
JsonObject jsonRequest = ClientDetailsEntityJsonProcessor.serialize(template, null, null);
|
||||||
|
|
||||||
|
/*
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.add("Content-type", "application/json");
|
||||||
|
headers.add("Accept", "application/json");
|
||||||
|
*/
|
||||||
|
|
||||||
|
String registered = restTemplate.postForObject(serverConfig.getRegistrationEndpointUri(), jsonRequest.toString(), String.class);
|
||||||
|
// TODO: handle HTTP errors
|
||||||
|
|
||||||
|
// TODO: save registration token and other important bits
|
||||||
|
ClientDetailsEntity client = ClientDetailsEntityJsonProcessor.parse(registered);
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,255 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.mitre.openid.connect;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mitre.jose.JWEAlgorithmEmbed;
|
||||||
|
import org.mitre.jose.JWEEncryptionMethodEmbed;
|
||||||
|
import org.mitre.jose.JWSAlgorithmEmbed;
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity.AppType;
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity.SubjectType;
|
||||||
|
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jricher
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ClientDetailsEntityJsonProcessor {
|
||||||
|
|
||||||
|
private static Gson gson = new Gson();
|
||||||
|
private static JsonParser parser = new JsonParser();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Create an unbound ClientDetailsEntity from the given JSON string.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* @return the entity if successful, null otherwise
|
||||||
|
*/
|
||||||
|
public static ClientDetailsEntity parse(String jsonString) {
|
||||||
|
JsonElement jsonEl = parser.parse(jsonString);
|
||||||
|
if (jsonEl.isJsonObject()) {
|
||||||
|
|
||||||
|
JsonObject o = jsonEl.getAsJsonObject();
|
||||||
|
ClientDetailsEntity c = new ClientDetailsEntity();
|
||||||
|
|
||||||
|
// TODO: make these field names into constants
|
||||||
|
|
||||||
|
// these two fields should only be sent in the update request, and MUST match existing values
|
||||||
|
c.setClientId(getAsString(o, "client_id"));
|
||||||
|
c.setClientSecret(getAsString(o, "client_secret"));
|
||||||
|
|
||||||
|
// OAuth DynReg
|
||||||
|
c.setRedirectUris(getAsStringSet(o, "redirect_uris"));
|
||||||
|
c.setClientName(getAsString(o, "client_name"));
|
||||||
|
c.setClientUri(getAsString(o, "client_uri"));
|
||||||
|
c.setLogoUri(getAsString(o, "logo_uri"));
|
||||||
|
c.setContacts(getAsStringSet(o, "contacts"));
|
||||||
|
c.setTosUri(getAsString(o, "tos_uri"));
|
||||||
|
|
||||||
|
String authMethod = getAsString(o, "token_endpoint_auth_method");
|
||||||
|
if (authMethod != null) {
|
||||||
|
c.setTokenEndpointAuthMethod(AuthMethod.getByValue(authMethod));
|
||||||
|
}
|
||||||
|
|
||||||
|
// scope is a space-separated string
|
||||||
|
String scope = getAsString(o, "scope");
|
||||||
|
if (scope != null) {
|
||||||
|
c.setScope(Sets.newHashSet(Splitter.on(" ").split(scope)));
|
||||||
|
}
|
||||||
|
|
||||||
|
c.setGrantTypes(getAsStringSet(o, "grant_types"));
|
||||||
|
c.setPolicyUri(getAsString(o, "policy_uri"));
|
||||||
|
c.setJwksUri(getAsString(o, "jwks_uri"));
|
||||||
|
|
||||||
|
|
||||||
|
// OIDC Additions
|
||||||
|
String appType = getAsString(o, "application_type");
|
||||||
|
if (appType != null) {
|
||||||
|
c.setApplicationType(AppType.getByValue(appType));
|
||||||
|
}
|
||||||
|
|
||||||
|
c.setSectorIdentifierUri(getAsString(o, "sector_identifier_uri"));
|
||||||
|
|
||||||
|
String subjectType = getAsString(o, "subject_type");
|
||||||
|
if (subjectType != null) {
|
||||||
|
c.setSubjectType(SubjectType.getByValue(subjectType));
|
||||||
|
}
|
||||||
|
|
||||||
|
c.setRequestObjectSigningAlg(getAsJwsAlgorithm(o, "request_object_signing_alg"));
|
||||||
|
|
||||||
|
c.setUserInfoSignedResponseAlg(getAsJwsAlgorithm(o, "userinfo_signed_response_alg"));
|
||||||
|
c.setUserInfoEncryptedResponseAlg(getAsJweAlgorithm(o, "userinfo_encrypted_response_alg"));
|
||||||
|
c.setUserInfoEncryptedResponseEnc(getAsJweEncryptionMethod(o, "userinfo_encrypted_response_enc"));
|
||||||
|
|
||||||
|
c.setIdTokenSignedResponseAlg(getAsJwsAlgorithm(o, "id_token_signed_response_alg"));
|
||||||
|
c.setIdTokenEncryptedResponseAlg(getAsJweAlgorithm(o, "id_token_encrypted_response_alg"));
|
||||||
|
c.setIdTokenEncryptedResponseEnc(getAsJweEncryptionMethod(o, "id_token_encrypted_response_enc"));
|
||||||
|
|
||||||
|
if (o.has("default_max_age")) {
|
||||||
|
if (o.get("default_max_age").isJsonPrimitive()) {
|
||||||
|
c.setDefaultMaxAge(o.get("default_max_age").getAsInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.has("require_auth_time")) {
|
||||||
|
if (o.get("require_auth_time").isJsonPrimitive()) {
|
||||||
|
c.setRequireAuthTime(o.get("require_auth_time").getAsBoolean());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.setDefaultACRvalues(getAsStringSet(o, "default_acr_values"));
|
||||||
|
c.setInitiateLoginUri(getAsString(o, "initiate_login_uri"));
|
||||||
|
c.setPostLogoutRedirectUri(getAsString(o, "post_logout_redirect_uri"));
|
||||||
|
c.setRequestUris(getAsStringSet(o, "request_uris"));
|
||||||
|
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonElement getAsArray(Set<String> value) {
|
||||||
|
return gson.toJsonTree(value, new TypeToken<Set<String>>(){}.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param c
|
||||||
|
* @param token
|
||||||
|
* @param registrationUri
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static JsonObject serialize(ClientDetailsEntity c, OAuth2AccessTokenEntity token, String registrationUri) {
|
||||||
|
JsonObject o = new JsonObject();
|
||||||
|
|
||||||
|
o.addProperty("client_id", c.getClientId());
|
||||||
|
if (c.getClientSecret() != null) {
|
||||||
|
o.addProperty("client_secret", c.getClientSecret());
|
||||||
|
o.addProperty("expires_at", 0); // TODO: do we want to let secrets expire?
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.getCreatedAt() != null) {
|
||||||
|
o.addProperty("issued_at", c.getCreatedAt().getTime());
|
||||||
|
}
|
||||||
|
if (token != null) {
|
||||||
|
o.addProperty("registration_access_token", token.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registrationUri != null) {
|
||||||
|
o.addProperty("registration_client_uri", registrationUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// add in all other client properties
|
||||||
|
|
||||||
|
// OAuth DynReg
|
||||||
|
o.add("redirect_uris", getAsArray(c.getRedirectUris()));
|
||||||
|
o.addProperty("client_name", c.getClientName());
|
||||||
|
o.addProperty("client_uri", c.getClientUri());
|
||||||
|
o.addProperty("logo_uri", c.getLogoUri());
|
||||||
|
o.add("contacts", getAsArray(c.getContacts()));
|
||||||
|
o.addProperty("tos_uri", c.getTosUri());
|
||||||
|
o.addProperty("token_endpoint_auth_method", c.getTokenEndpointAuthMethod() != null ? c.getTokenEndpointAuthMethod().getValue() : null);
|
||||||
|
o.addProperty("scope", c.getScope() != null ? Joiner.on(" ").join(c.getScope()) : null);
|
||||||
|
o.add("grant_types", getAsArray(c.getGrantTypes()));
|
||||||
|
o.addProperty("policy_uri", c.getPolicyUri());
|
||||||
|
o.addProperty("jwks_uri", c.getJwksUri());
|
||||||
|
|
||||||
|
// OIDC Registration
|
||||||
|
o.addProperty("application_type", c.getApplicationType() != null ? c.getApplicationType().getValue() : null);
|
||||||
|
o.addProperty("sector_identifier_uri", c.getSectorIdentifierUri());
|
||||||
|
o.addProperty("subject_type", c.getSubjectType() != null ? c.getSubjectType().getValue() : null);
|
||||||
|
o.addProperty("request_object_signing_alg", c.getRequestObjectSigningAlg() != null ? c.getRequestObjectSigningAlg().getAlgorithmName() : null);
|
||||||
|
o.addProperty("userinfo_signed_response_alg", c.getUserInfoSignedResponseAlg() != null ? c.getUserInfoSignedResponseAlg().getAlgorithmName() : null);
|
||||||
|
o.addProperty("userinfo_encrypted_response_alg", c.getUserInfoEncryptedResponseAlg() != null ? c.getUserInfoEncryptedResponseAlg().getAlgorithmName() : null);
|
||||||
|
o.addProperty("userinfo_encrypted_response_enc", c.getUserInfoEncryptedResponseEnc() != null ? c.getUserInfoEncryptedResponseEnc().getAlgorithmName() : null);
|
||||||
|
o.addProperty("id_token_signed_response_alg", c.getIdTokenSignedResponseAlg() != null ? c.getIdTokenSignedResponseAlg().getAlgorithmName() : null);
|
||||||
|
o.addProperty("id_token_encrypted_response_alg", c.getIdTokenEncryptedResponseAlg() != null ? c.getIdTokenEncryptedResponseAlg().getAlgorithmName() : null);
|
||||||
|
o.addProperty("id_token_encrypted_response_enc", c.getIdTokenEncryptedResponseEnc() != null ? c.getIdTokenEncryptedResponseEnc().getAlgorithmName() : null);
|
||||||
|
o.addProperty("default_max_age", c.getDefaultMaxAge());
|
||||||
|
o.addProperty("require_auth_time", c.getRequireAuthTime());
|
||||||
|
o.add("default_acr_values", getAsArray(c.getDefaultACRvalues()));
|
||||||
|
o.addProperty("initiate_login_uri", c.getInitiateLoginUri());
|
||||||
|
o.addProperty("post_logout_redirect_uri", c.getPostLogoutRedirectUri());
|
||||||
|
o.add("request_uris", getAsArray(c.getRequestUris()));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the given member as a JWE Algorithm, null if it doesn't exist
|
||||||
|
*/
|
||||||
|
public static JWEAlgorithmEmbed getAsJweAlgorithm(JsonObject o, String member) {
|
||||||
|
String s = getAsString(o, member);
|
||||||
|
if (s != null) {
|
||||||
|
return JWEAlgorithmEmbed.getForAlgorithmName(s);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the given member as a JWE Encryption Method, null if it doesn't exist
|
||||||
|
*/
|
||||||
|
public static JWEEncryptionMethodEmbed getAsJweEncryptionMethod(JsonObject o, String member) {
|
||||||
|
String s = getAsString(o, member);
|
||||||
|
if (s != null) {
|
||||||
|
return JWEEncryptionMethodEmbed.getForAlgorithmName(s);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the given member as a JWS Algorithm, null if it doesn't exist
|
||||||
|
*/
|
||||||
|
public static JWSAlgorithmEmbed getAsJwsAlgorithm(JsonObject o, String member) {
|
||||||
|
String s = getAsString(o, member);
|
||||||
|
if (s != null) {
|
||||||
|
return JWSAlgorithmEmbed.getForAlgorithmName(s);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the given member as a string, null if it doesn't exist
|
||||||
|
*/
|
||||||
|
public static String getAsString(JsonObject o, String member) {
|
||||||
|
if (o.has(member)) {
|
||||||
|
JsonElement e = o.get(member);
|
||||||
|
if (e != null && e.isJsonPrimitive()) {
|
||||||
|
return e.getAsString();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the given given member as a set of strings, null if it doesn't exist
|
||||||
|
*/
|
||||||
|
public static Set<String> getAsStringSet(JsonObject o, String member) throws JsonSyntaxException {
|
||||||
|
if (o.has(member)) {
|
||||||
|
return gson.fromJson(o.get(member), new TypeToken<Set<String>>(){}.getType());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,23 +6,20 @@ package org.mitre.openid.connect.view;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||||
|
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.servlet.view.AbstractView;
|
import org.springframework.web.servlet.view.AbstractView;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonIOException;
|
import com.google.gson.JsonIOException;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -53,57 +50,9 @@ public class ClientInformationResponseView extends AbstractView {
|
||||||
code = HttpStatus.OK;
|
code = HttpStatus.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject o = new JsonObject();
|
|
||||||
|
|
||||||
o.addProperty("client_id", c.getClientId());
|
|
||||||
if (c.getClientSecret() != null) {
|
|
||||||
o.addProperty("client_secret", c.getClientSecret());
|
|
||||||
o.addProperty("expires_at", 0); // TODO: do we want to let secrets expire?
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c.getCreatedAt() != null) {
|
|
||||||
o.addProperty("issued_at", c.getCreatedAt().getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
o.addProperty("registration_access_token", token.getValue());
|
|
||||||
|
|
||||||
// TODO: urlencode the client id for safety?
|
// TODO: urlencode the client id for safety?
|
||||||
String uri = request.getRequestURL() + "/" + c.getClientId();
|
String uri = request.getRequestURL() + "/" + c.getClientId();
|
||||||
o.addProperty("registration_client_uri", uri);
|
JsonObject o = ClientDetailsEntityJsonProcessor.serialize(c, token, uri);
|
||||||
|
|
||||||
|
|
||||||
// add in all other client properties
|
|
||||||
|
|
||||||
// OAuth DynReg
|
|
||||||
o.add("redirect_uris", getAsArray(c.getRedirectUris()));
|
|
||||||
o.addProperty("client_name", c.getClientName());
|
|
||||||
o.addProperty("client_uri", c.getClientUri());
|
|
||||||
o.addProperty("logo_uri", c.getLogoUri());
|
|
||||||
o.add("contacts", getAsArray(c.getContacts()));
|
|
||||||
o.addProperty("tos_uri", c.getTosUri());
|
|
||||||
o.addProperty("token_endpoint_auth_method", c.getTokenEndpointAuthMethod() != null ? c.getTokenEndpointAuthMethod().getValue() : null);
|
|
||||||
o.addProperty("scope", c.getScope() != null ? Joiner.on(" ").join(c.getScope()) : null);
|
|
||||||
o.add("grant_types", getAsArray(c.getGrantTypes()));
|
|
||||||
o.addProperty("policy_uri", c.getPolicyUri());
|
|
||||||
o.addProperty("jwks_uri", c.getJwksUri());
|
|
||||||
|
|
||||||
// OIDC Registration
|
|
||||||
o.addProperty("application_type", c.getApplicationType() != null ? c.getApplicationType().getValue() : null);
|
|
||||||
o.addProperty("sector_identifier_uri", c.getSectorIdentifierUri());
|
|
||||||
o.addProperty("subject_type", c.getSubjectType() != null ? c.getSubjectType().getValue() : null);
|
|
||||||
o.addProperty("request_object_signing_alg", c.getRequestObjectSigningAlg() != null ? c.getRequestObjectSigningAlg().getAlgorithmName() : null);
|
|
||||||
o.addProperty("userinfo_signed_response_alg", c.getUserInfoSignedResponseAlg() != null ? c.getUserInfoSignedResponseAlg().getAlgorithmName() : null);
|
|
||||||
o.addProperty("userinfo_encrypted_response_alg", c.getUserInfoEncryptedResponseAlg() != null ? c.getUserInfoEncryptedResponseAlg().getAlgorithmName() : null);
|
|
||||||
o.addProperty("userinfo_encrypted_response_enc", c.getUserInfoEncryptedResponseEnc() != null ? c.getUserInfoEncryptedResponseEnc().getAlgorithmName() : null);
|
|
||||||
o.addProperty("id_token_signed_response_alg", c.getIdTokenSignedResponseAlg() != null ? c.getIdTokenSignedResponseAlg().getAlgorithmName() : null);
|
|
||||||
o.addProperty("id_token_encrypted_response_alg", c.getIdTokenEncryptedResponseAlg() != null ? c.getIdTokenEncryptedResponseAlg().getAlgorithmName() : null);
|
|
||||||
o.addProperty("id_token_encrypted_response_enc", c.getIdTokenEncryptedResponseEnc() != null ? c.getIdTokenEncryptedResponseEnc().getAlgorithmName() : null);
|
|
||||||
o.addProperty("default_max_age", c.getDefaultMaxAge());
|
|
||||||
o.addProperty("require_auth_time", c.getRequireAuthTime());
|
|
||||||
o.add("default_acr_values", getAsArray(c.getDefaultACRvalues()));
|
|
||||||
o.addProperty("initiate_login_uri", c.getInitiateLoginUri());
|
|
||||||
o.addProperty("post_logout_redirect_uri", c.getPostLogoutRedirectUri());
|
|
||||||
o.add("request_uris", getAsArray(c.getRequestUris()));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Writer out = response.getWriter();
|
Writer out = response.getWriter();
|
||||||
|
@ -118,8 +67,4 @@ public class ClientInformationResponseView extends AbstractView {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonElement getAsArray(Set<String> value) {
|
|
||||||
return gson.toJsonTree(value, new TypeToken<Set<String>>(){}.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,18 +5,14 @@ package org.mitre.openid.connect.web;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.mitre.jose.JWEAlgorithmEmbed;
|
|
||||||
import org.mitre.jose.JWEEncryptionMethodEmbed;
|
|
||||||
import org.mitre.jose.JWSAlgorithmEmbed;
|
|
||||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
import org.mitre.oauth2.model.ClientDetailsEntity.AppType;
|
|
||||||
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
|
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
|
||||||
import org.mitre.oauth2.model.ClientDetailsEntity.SubjectType;
|
|
||||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||||
import org.mitre.oauth2.model.SystemScope;
|
import org.mitre.oauth2.model.SystemScope;
|
||||||
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
||||||
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
||||||
import org.mitre.oauth2.service.SystemScopeService;
|
import org.mitre.oauth2.service.SystemScopeService;
|
||||||
|
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -34,14 +30,9 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.JsonSyntaxException;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping(value = "register")
|
@RequestMapping(value = "register")
|
||||||
|
@ -57,8 +48,6 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
private SystemScopeService scopeService;
|
private SystemScopeService scopeService;
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(ClientDynamicRegistrationEndpoint.class);
|
private static Logger logger = LoggerFactory.getLogger(ClientDynamicRegistrationEndpoint.class);
|
||||||
private JsonParser parser = new JsonParser();
|
|
||||||
private Gson gson = new Gson();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Client, issue a client ID, and create a registration access token.
|
* Create a new Client, issue a client ID, and create a registration access token.
|
||||||
|
@ -70,7 +59,7 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
@RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
|
@RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
|
||||||
public String registerNewClient(@RequestBody String jsonString, Model m) {
|
public String registerNewClient(@RequestBody String jsonString, Model m) {
|
||||||
|
|
||||||
ClientDetailsEntity newClient = parse(jsonString);
|
ClientDetailsEntity newClient = ClientDetailsEntityJsonProcessor.parse(jsonString);
|
||||||
|
|
||||||
if (newClient != null) {
|
if (newClient != null) {
|
||||||
// it parsed!
|
// it parsed!
|
||||||
|
@ -203,7 +192,7 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
public String updateClient(@PathVariable("id") String clientId, @RequestBody String jsonString, Model m, OAuth2Authentication auth) {
|
public String updateClient(@PathVariable("id") String clientId, @RequestBody String jsonString, Model m, OAuth2Authentication auth) {
|
||||||
|
|
||||||
|
|
||||||
ClientDetailsEntity newClient = parse(jsonString);
|
ClientDetailsEntity newClient = ClientDetailsEntityJsonProcessor.parse(jsonString);
|
||||||
ClientDetailsEntity oldClient = clientService.loadClientByClientId(clientId);
|
ClientDetailsEntity oldClient = clientService.loadClientByClientId(clientId);
|
||||||
|
|
||||||
if (newClient != null && oldClient != null // we have an existing client and the new one parsed
|
if (newClient != null && oldClient != null // we have an existing client and the new one parsed
|
||||||
|
@ -301,159 +290,6 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Create an unbound ClientDetailsEntity from the given JSON string.
|
|
||||||
*
|
|
||||||
* @param jsonString
|
|
||||||
* @return the entity if successful, null otherwise
|
|
||||||
*/
|
|
||||||
private ClientDetailsEntity parse(String jsonString) {
|
|
||||||
JsonElement jsonEl = parser.parse(jsonString);
|
|
||||||
if (jsonEl.isJsonObject()) {
|
|
||||||
|
|
||||||
JsonObject o = jsonEl.getAsJsonObject();
|
|
||||||
ClientDetailsEntity c = new ClientDetailsEntity();
|
|
||||||
|
|
||||||
// TODO: make these field names into constants
|
|
||||||
|
|
||||||
// these two fields should only be sent in the update request, and MUST match existing values
|
|
||||||
c.setClientId(getAsString(o, "client_id"));
|
|
||||||
c.setClientSecret(getAsString(o, "client_secret"));
|
|
||||||
|
|
||||||
// OAuth DynReg
|
|
||||||
c.setRedirectUris(getAsStringSet(o, "redirect_uris"));
|
|
||||||
c.setClientName(getAsString(o, "client_name"));
|
|
||||||
c.setClientUri(getAsString(o, "client_uri"));
|
|
||||||
c.setLogoUri(getAsString(o, "logo_uri"));
|
|
||||||
c.setContacts(getAsStringSet(o, "contacts"));
|
|
||||||
c.setTosUri(getAsString(o, "tos_uri"));
|
|
||||||
|
|
||||||
String authMethod = getAsString(o, "token_endpoint_auth_method");
|
|
||||||
if (authMethod != null) {
|
|
||||||
c.setTokenEndpointAuthMethod(AuthMethod.getByValue(authMethod));
|
|
||||||
}
|
|
||||||
|
|
||||||
// scope is a space-separated string
|
|
||||||
String scope = getAsString(o, "scope");
|
|
||||||
if (scope != null) {
|
|
||||||
c.setScope(Sets.newHashSet(Splitter.on(" ").split(scope)));
|
|
||||||
}
|
|
||||||
|
|
||||||
c.setGrantTypes(getAsStringSet(o, "grant_types"));
|
|
||||||
c.setPolicyUri(getAsString(o, "policy_uri"));
|
|
||||||
c.setJwksUri(getAsString(o, "jwks_uri"));
|
|
||||||
|
|
||||||
|
|
||||||
// OIDC Additions
|
|
||||||
String appType = getAsString(o, "application_type");
|
|
||||||
if (appType != null) {
|
|
||||||
c.setApplicationType(AppType.getByValue(appType));
|
|
||||||
}
|
|
||||||
|
|
||||||
c.setSectorIdentifierUri(getAsString(o, "sector_identifier_uri"));
|
|
||||||
|
|
||||||
String subjectType = getAsString(o, "subject_type");
|
|
||||||
if (subjectType != null) {
|
|
||||||
c.setSubjectType(SubjectType.getByValue(subjectType));
|
|
||||||
}
|
|
||||||
|
|
||||||
c.setRequestObjectSigningAlg(getAsJwsAlgorithm(o, "request_object_signing_alg"));
|
|
||||||
|
|
||||||
c.setUserInfoSignedResponseAlg(getAsJwsAlgorithm(o, "userinfo_signed_response_alg"));
|
|
||||||
c.setUserInfoEncryptedResponseAlg(getAsJweAlgorithm(o, "userinfo_encrypted_response_alg"));
|
|
||||||
c.setUserInfoEncryptedResponseEnc(getAsJweEncryptionMethod(o, "userinfo_encrypted_response_enc"));
|
|
||||||
|
|
||||||
c.setIdTokenSignedResponseAlg(getAsJwsAlgorithm(o, "id_token_signed_response_alg"));
|
|
||||||
c.setIdTokenEncryptedResponseAlg(getAsJweAlgorithm(o, "id_token_encrypted_response_alg"));
|
|
||||||
c.setIdTokenEncryptedResponseEnc(getAsJweEncryptionMethod(o, "id_token_encrypted_response_enc"));
|
|
||||||
|
|
||||||
if (o.has("default_max_age")) {
|
|
||||||
if (o.get("default_max_age").isJsonPrimitive()) {
|
|
||||||
c.setDefaultMaxAge(o.get("default_max_age").getAsInt());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o.has("require_auth_time")) {
|
|
||||||
if (o.get("require_auth_time").isJsonPrimitive()) {
|
|
||||||
c.setRequireAuthTime(o.get("require_auth_time").getAsBoolean());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.setDefaultACRvalues(getAsStringSet(o, "default_acr_values"));
|
|
||||||
c.setInitiateLoginUri(getAsString(o, "initiate_login_uri"));
|
|
||||||
c.setPostLogoutRedirectUri(getAsString(o, "post_logout_redirect_uri"));
|
|
||||||
c.setRequestUris(getAsStringSet(o, "request_uris"));
|
|
||||||
|
|
||||||
return c;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the given given member as a set of strings, null if it doesn't exist
|
|
||||||
*/
|
|
||||||
private Set<String> getAsStringSet(JsonObject o, String member) throws JsonSyntaxException {
|
|
||||||
if (o.has(member)) {
|
|
||||||
return gson.fromJson(o.get(member), new TypeToken<Set<String>>(){}.getType());
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the given member as a string, null if it doesn't exist
|
|
||||||
*/
|
|
||||||
private String getAsString(JsonObject o, String member) {
|
|
||||||
if (o.has(member)) {
|
|
||||||
JsonElement e = o.get(member);
|
|
||||||
if (e != null && e.isJsonPrimitive()) {
|
|
||||||
return e.getAsString();
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the given member as a JWS Algorithm, null if it doesn't exist
|
|
||||||
*/
|
|
||||||
private JWSAlgorithmEmbed getAsJwsAlgorithm(JsonObject o, String member) {
|
|
||||||
String s = getAsString(o, member);
|
|
||||||
if (s != null) {
|
|
||||||
return JWSAlgorithmEmbed.getForAlgorithmName(s);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the given member as a JWE Algorithm, null if it doesn't exist
|
|
||||||
*/
|
|
||||||
private JWEAlgorithmEmbed getAsJweAlgorithm(JsonObject o, String member) {
|
|
||||||
String s = getAsString(o, member);
|
|
||||||
if (s != null) {
|
|
||||||
return JWEAlgorithmEmbed.getForAlgorithmName(s);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the given member as a JWE Encryption Method, null if it doesn't exist
|
|
||||||
*/
|
|
||||||
private JWEEncryptionMethodEmbed getAsJweEncryptionMethod(JsonObject o, String member) {
|
|
||||||
String s = getAsString(o, member);
|
|
||||||
if (s != null) {
|
|
||||||
return JWEEncryptionMethodEmbed.getForAlgorithmName(s);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @param client
|
* @param client
|
||||||
* @return
|
* @return
|
||||||
|
|
Loading…
Reference in New Issue