Merge pull request #1707 from stianst/client-reg

Refactored client registration service
This commit is contained in:
Stian Thorgersen 2015-10-12 11:15:19 +02:00
commit 4f7979d9fc
12 changed files with 231 additions and 40 deletions

View file

@ -231,7 +231,7 @@ public class ClientRegistration {
public ClientRegistration build() {
ClientRegistration clientRegistration = new ClientRegistration();
clientRegistration.clientRegistrationUrl = authServerUrl + "/realms/" + realm + "/client-registration";
clientRegistration.clientRegistrationUrl = authServerUrl + "/realms/" + realm + "/client-registration/default";
clientRegistration.httpClient = httpClient != null ? httpClient : HttpClients.createDefault();
clientRegistration.auth = auth;

View file

@ -0,0 +1,16 @@
package org.keycloak.services.clientregistration;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface ClientRegistrationProvider extends Provider {
void setRealm(RealmModel realm);
void setEvent(EventBuilder event);
}

View file

@ -0,0 +1,9 @@
package org.keycloak.services.clientregistration;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface ClientRegistrationProviderFactory extends ProviderFactory<ClientRegistrationProvider> {
}

View file

@ -0,0 +1,37 @@
package org.keycloak.services.clientregistration;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.managers.AppAuthManager;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistrationService {
private RealmModel realm;
private EventBuilder event;
@Context
private KeycloakSession session;
public ClientRegistrationService(RealmModel realm, EventBuilder event) {
this.realm = realm;
this.event = event;
}
@Path("{provider}")
public Object getProvider(@PathParam("provider") String providerId) {
ClientRegistrationProvider provider = session.getProvider(ClientRegistrationProvider.class, providerId);
provider.setRealm(realm);
provider.setEvent(event);
return provider;
}
}

View file

@ -0,0 +1,30 @@
package org.keycloak.services.clientregistration;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistrationSpi implements Spi {
@Override
public boolean isInternal() {
return false;
}
@Override
public String getName() {
return "client-registration";
}
@Override
public Class<? extends Provider> getProviderClass() {
return ClientRegistrationProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return ClientRegistrationProviderFactory.class;
}
}

View file

@ -1,14 +1,9 @@
package org.keycloak.services.resources;
package org.keycloak.services.clientregistration;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.UnauthorizedException;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.exportimport.ClientDescriptionConverter;
import org.keycloak.exportimport.KeycloakClientDescriptionConverter;
import org.keycloak.models.*;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
@ -16,13 +11,11 @@ import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ -31,52 +24,37 @@ import java.net.URI;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistrationService {
public class DefaultClientRegistrationProvider implements ClientRegistrationProvider {
protected static final Logger logger = Logger.getLogger(ClientRegistrationService.class);
private static final Logger logger = Logger.getLogger(DefaultClientRegistrationProvider.class);
private KeycloakSession session;
private EventBuilder event;
private RealmModel realm;
private EventBuilder event;
@Context
private KeycloakSession session;
private AppAuthManager authManager = new AppAuthManager();
public ClientRegistrationService(RealmModel realm, EventBuilder event) {
this.realm = realm;
this.event = event;
public DefaultClientRegistrationProvider(KeycloakSession session) {
this.session = session;
}
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN })
public Response create(String description, @QueryParam("format") String format) {
@Consumes(MediaType.APPLICATION_JSON)
public Response create(ClientRepresentation client) {
event.event(EventType.CLIENT_REGISTER);
authenticate(true, null);
if (format == null) {
format = KeycloakClientDescriptionConverter.ID;
}
ClientDescriptionConverter converter = session.getProvider(ClientDescriptionConverter.class, format);
if (converter == null) {
throw new BadRequestException("Invalid format");
}
ClientRepresentation rep = converter.convertToInternal(description);
try {
ClientModel clientModel = RepresentationToModel.createClient(session, realm, rep, true);
rep = ModelToRepresentation.toRepresentation(clientModel);
ClientModel clientModel = RepresentationToModel.createClient(session, realm, client, true);
client = ModelToRepresentation.toRepresentation(clientModel);
URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(clientModel.getId()).build();
logger.infov("Created client {0}", rep.getClientId());
logger.infov("Created client {0}", client.getClientId());
event.client(rep.getClientId()).success();
return Response.created(uri).entity(rep).build();
event.client(client.getClientId()).success();
return Response.created(uri).entity(client).build();
} catch (ModelDuplicateException e) {
return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
return ErrorResponse.exists("Client " + client.getClientId() + " already exists");
}
}
@ -122,13 +100,19 @@ public class ClientRegistrationService {
}
}
@Override
public void close() {
}
private ClientModel authenticate(boolean create, String clientId) {
String authorizationHeader = session.getContext().getRequestHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
boolean bearer = authorizationHeader != null && authorizationHeader.split(" ")[0].equalsIgnoreCase("Bearer");
if (bearer) {
AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm);
AuthenticationManager.AuthResult authResult = new AppAuthManager().authenticateBearerToken(session, realm);
AccessToken.Access realmAccess = authResult.getToken().getResourceAccess(Constants.REALM_MANAGEMENT_CLIENT_ID);
if (realmAccess != null) {
if (realmAccess.isUserInRole(AdminRoles.MANAGE_CLIENTS)) {
@ -158,4 +142,14 @@ public class ClientRegistrationService {
throw new ForbiddenException();
}
@Override
public void setRealm(RealmModel realm) {
this.realm = realm;
}
@Override
public void setEvent(EventBuilder event) {
this.event = event;
}
}

View file

@ -0,0 +1,34 @@
package org.keycloak.services.clientregistration;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultClientRegistrationProviderFactory implements ClientRegistrationProviderFactory {
@Override
public ClientRegistrationProvider create(KeycloakSession session) {
return new DefaultClientRegistrationProvider(session);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return "default";
}
}

View file

@ -0,0 +1,34 @@
package org.keycloak.services.clientregistration;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class OIDCClientRegistrationProvider implements ClientRegistrationProvider {
private KeycloakSession session;
private RealmModel realm;
private EventBuilder event;
public OIDCClientRegistrationProvider(KeycloakSession session) {
this.session = session;
}
@Override
public void close() {
}
@Override
public void setRealm(RealmModel realm) {
this.realm = realm;
}
@Override
public void setEvent(EventBuilder event) {
this.event = event;
}
}

View file

@ -0,0 +1,34 @@
package org.keycloak.services.clientregistration;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class OIDCClientRegistrationProviderFactory implements ClientRegistrationProviderFactory {
@Override
public ClientRegistrationProvider create(KeycloakSession session) {
return new OIDCClientRegistrationProvider(session);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return "openid-connect";
}
}

View file

@ -13,6 +13,7 @@ import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.LoginProtocolFactory;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.services.clientregistration.ClientRegistrationService;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.BruteForceProtector;
import org.keycloak.services.managers.RealmManager;

View file

@ -8,3 +8,4 @@ org.keycloak.authentication.ClientAuthenticatorSpi
org.keycloak.authentication.RequiredActionSpi
org.keycloak.authentication.FormAuthenticatorSpi
org.keycloak.authentication.FormActionSpi
org.keycloak.services.clientregistration.ClientRegistrationSpi

View file

@ -0,0 +1 @@
org.keycloak.services.clientregistration.DefaultClientRegistrationProviderFactory