Skip to content

Commit

Permalink
Merge branch 'master' of github.com:openremote/openremote
Browse files Browse the repository at this point in the history
  • Loading branch information
robin-dekkers committed May 26, 2020
2 parents f8bcbc1 + b52f7ec commit 6245995
Show file tree
Hide file tree
Showing 41 changed files with 1,367 additions and 196 deletions.
2 changes: 1 addition & 1 deletion container/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ dependencies {

jar {
archivesBaseName = "openremote-${project.name}"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016, OpenRemote Inc.
* Copyright 2020, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
Expand All @@ -21,52 +21,21 @@

import javax.ws.rs.FormParam;

public class AuthForm {
public abstract class AuthForm {

@FormParam("client_id")
public String clientId;

@FormParam("username")
public String username;

@FormParam("password")
public String password;

@FormParam("grant_type")
public String grantType;

public AuthForm() {
}

public AuthForm setClientId(String clientId) {
this.clientId = clientId;
return this;
}

public AuthForm setUsername(String username) {
this.username = username;
return this;
}

public AuthForm setPassword(String password) {
this.password = password;
return this;
}

public AuthForm setGrantType(String grantType) {
this.grantType = grantType;
return this;
}

public AuthForm(String clientId, String username, String password) {
this(clientId, username, password, "password");
}

public AuthForm(String clientId, String username, String password, String grantType) {
this.clientId = clientId;
this.username = username;
this.password = password;
this.grantType = grantType;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2020, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.container.security;

import javax.ws.rs.FormParam;

public class ClientCredentialsAuthForm extends AuthForm {

@FormParam("client_secret")
public String clientSecret;

public ClientCredentialsAuthForm setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
return this;
}

public ClientCredentialsAuthForm(String clientId, String clientSecret) {
this(clientId, clientSecret, "client_credentials");
}

public ClientCredentialsAuthForm(String clientId, String clientSecret, String grantType) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.grantType = grantType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2020, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.container.security;

import javax.ws.rs.FormParam;

public class PasswordAuthForm extends AuthForm {

@FormParam("username")
public String username;

@FormParam("password")
public String password;

public PasswordAuthForm setUsername(String username) {
this.username = username;
return this;
}

public PasswordAuthForm setPassword(String password) {
this.password = password;
return this;
}

public PasswordAuthForm(String clientId, String username, String password) {
this(clientId, username, password, "password");
}

public PasswordAuthForm(String clientId, String username, String password, String grantType) {
this.clientId = clientId;
this.username = username;
this.password = password;
this.grantType = grantType;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ public KeycloakResource getKeycloak() {
.proxy(KeycloakResource.class);
}

public KeycloakResource getExternalKeycloak() {
return getTarget(httpClient, keycloakServiceUri.build(), null, null, externalServerUri.build())
.proxy(KeycloakResource.class);
}

public RealmsResource getRealms(ClientRequestInfo clientRequestInfo) {
return getRealms(clientRequestInfo.getRemoteAddress(), clientRequestInfo.getAccessToken());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.representations.idm.PublishedRealmRepresentation;
import org.openremote.container.security.AuthForm;
import org.openremote.container.security.PasswordAuthForm;
import org.openremote.container.security.ClientCredentialsAuthForm;

import javax.ws.rs.*;
import javax.ws.rs.core.Response;
Expand All @@ -42,7 +43,13 @@ public interface KeycloakResource {
@Path("realms/{realm}/protocol/openid-connect/token")
@Consumes(APPLICATION_FORM_URLENCODED)
@Produces(APPLICATION_JSON)
AccessTokenResponse getAccessToken(@PathParam("realm") String realm, @BeanParam AuthForm authForm);
AccessTokenResponse getAccessToken(@PathParam("realm") String realm, @BeanParam PasswordAuthForm authForm);

@POST
@Path("realms/{realm}/protocol/openid-connect/token")
@Consumes(APPLICATION_FORM_URLENCODED)
@Produces(APPLICATION_JSON)
AccessTokenResponse getAccessToken(@PathParam("realm") String realm, @BeanParam ClientCredentialsAuthForm authForm);

@GET
@Path("realms/{realm}")
Expand All @@ -54,4 +61,4 @@ public interface KeycloakResource {
@Produces(APPLICATION_JSON)
AdapterConfig getAdapterConfig(@PathParam("realm") String realm, @PathParam("clientId") String clientId);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.container.web.socket;
package org.openremote.container.web;

public interface WebsocketConstants {
public interface ConnectionConstants {

String SESSION = "websocket.session";
String SESSION_KEY = "websocket.sessionKey";
String SEND_TO_ALL = "websocket.sendToAll";
String HANDSHAKE_AUTH = "websocket.auth";
String SESSION_OPEN = "websocket.sessionOpen";
String SESSION_CLOSE = "websocket.sessionClose";
String SESSION_CLOSE_ERROR = "websocket.sessionCloseError";
String SESSION = "connection.session";
String SESSION_KEY = "connection.sessionKey";
String SEND_TO_ALL = "connection.sendToAll";
String HANDSHAKE_AUTH = "connection.auth";
String SESSION_OPEN = "connection.sessionOpen";
String SESSION_CLOSE = "connection.sessionClose";
String SESSION_CLOSE_ERROR = "connection.sessionCloseError";

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.openremote.container.security.keycloak.AccessTokenAuthContext;
import org.openremote.container.web.socket.WebsocketAdapter;
import org.openremote.container.web.socket.WebsocketComponent;
import org.openremote.container.web.socket.WebsocketConstants;
import org.xnio.OptionMap;
import org.xnio.Options;
import org.xnio.Xnio;
Expand Down Expand Up @@ -112,7 +111,7 @@ public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest reques
throw new WebApplicationException("Unsupported user principal type: " + principal, INTERNAL_SERVER_ERROR);
}

config.getUserProperties().put(WebsocketConstants.HANDSHAKE_AUTH, authContext);
config.getUserProperties().put(ConnectionConstants.HANDSHAKE_AUTH, authContext);

super.modifyHandshake(config, request, response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.openremote.container.web.socket;

import org.openremote.container.security.AuthContext;
import org.openremote.container.web.ConnectionConstants;

import javax.websocket.CloseReason;
import javax.websocket.Endpoint;
Expand Down Expand Up @@ -48,14 +49,14 @@ public void onOpen(Session session, EndpointConfig config) {
session.setMaxIdleTimeout(0);
consumer.getEndpoint().getWebsocketSessions().add(session);
this.consumer.sendMessage(session.getId(), getHandshakeAuth(session), null, exchange -> {
exchange.getIn().setHeader(WebsocketConstants.SESSION, session);
exchange.getIn().setHeader(WebsocketConstants.SESSION_OPEN, true);
exchange.getIn().setHeader(ConnectionConstants.SESSION, session);
exchange.getIn().setHeader(ConnectionConstants.SESSION_OPEN, true);
});
session.addMessageHandler(String.class, message -> {
if (LOG.isLoggable(Level.FINE))
LOG.fine("Websocket session " + session.getId() + " message received: " + message);
this.consumer.sendMessage(session.getId(), getHandshakeAuth(session), message, exchange -> {
exchange.getIn().setHeader(WebsocketConstants.SESSION, session);
exchange.getIn().setHeader(ConnectionConstants.SESSION, session);
});
});
}
Expand All @@ -65,8 +66,8 @@ public void onClose(Session session, CloseReason closeReason) {
if (LOG.isLoggable(Level.FINE))
LOG.fine("Websocket session close: " + session.getId() + " " + closeReason);
this.consumer.sendMessage(session.getId(), getHandshakeAuth(session), closeReason, exchange -> {
exchange.getIn().setHeader(WebsocketConstants.SESSION, session);
exchange.getIn().setHeader(WebsocketConstants.SESSION_CLOSE, true);
exchange.getIn().setHeader(ConnectionConstants.SESSION, session);
exchange.getIn().setHeader(ConnectionConstants.SESSION_CLOSE, true);
});
consumer.getEndpoint().getWebsocketSessions().remove(session);
}
Expand All @@ -81,14 +82,14 @@ public void onError(Session session, Throwable thr) {
LOG.log(Level.INFO, "Websocket session error: " + session.getId(), thr);
}
this.consumer.sendMessage(session.getId(), getHandshakeAuth(session), thr, exchange -> {
exchange.getIn().setHeader(WebsocketConstants.SESSION, session);
exchange.getIn().setHeader(WebsocketConstants.SESSION_CLOSE_ERROR, true);
exchange.getIn().setHeader(ConnectionConstants.SESSION, session);
exchange.getIn().setHeader(ConnectionConstants.SESSION_CLOSE_ERROR, true);
});
consumer.getEndpoint().getWebsocketSessions().remove(session);
}

protected AuthContext getHandshakeAuth(Session session) {
AuthContext auth = (AuthContext) session.getUserProperties().get(WebsocketConstants.HANDSHAKE_AUTH);
AuthContext auth = (AuthContext) session.getUserProperties().get(ConnectionConstants.HANDSHAKE_AUTH);
if (auth == null)
throw new IllegalStateException("No authorization details in websocket session: " + session.getId());
return auth;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.camel.Processor;
import org.apache.camel.impl.DefaultConsumer;
import org.openremote.container.security.AuthContext;
import org.openremote.container.web.ConnectionConstants;
import org.openremote.model.Constants;

import java.util.function.Consumer;
Expand Down Expand Up @@ -62,7 +63,7 @@ public void sendMessage(final String sessionKey, final AuthContext authContext,

public void sendMessage(final String sessionKey, final AuthContext authContext, final Object message, Consumer<Exchange> exchangePreparer) {
final Exchange exchange = getEndpoint().createExchange();
exchange.getIn().setHeader(WebsocketConstants.SESSION_KEY, sessionKey);
exchange.getIn().setHeader(ConnectionConstants.SESSION_KEY, sessionKey);
exchange.getIn().setHeader(Constants.AUTH_CONTEXT, authContext);
exchange.getIn().setBody(message);
if (exchangePreparer != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.impl.DefaultProducer;
import org.openremote.container.web.ConnectionConstants;

import javax.websocket.Session;
import java.io.IOException;
Expand Down Expand Up @@ -53,7 +54,7 @@ public void process(Exchange exchange) throws Exception {
if (isSendToAllSet(in)) {
sendToAll(message, exchange);
} else {
String sessionKey = in.getHeader(WebsocketConstants.SESSION_KEY, String.class);
String sessionKey = in.getHeader(ConnectionConstants.SESSION_KEY, String.class);
if (sessionKey != null) {
Session websocket = getEndpoint().getComponent().getWebsocketSessions().get(sessionKey);
sendMessage(websocket, message);
Expand All @@ -68,7 +69,7 @@ public WebsocketEndpoint getEndpoint() {
}

protected boolean isSendToAllSet(Message in) {
Boolean value = in.getHeader(WebsocketConstants.SEND_TO_ALL, sendToAll, Boolean.class);
Boolean value = in.getHeader(ConnectionConstants.SEND_TO_ALL, sendToAll, Boolean.class);
return value == null ? false : value;
}

Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ firebaseAdminVersion = 6.1.0
simpleJavaMailVersion = 5.0.4
jaywayJsonPathVersion = 2.4.0
typescriptGeneratorVersion = 2.13.489
moquetteVersion = 0.13
4 changes: 3 additions & 1 deletion manager/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ dependencies {
compile ("io.netty:netty-codec-http:$nettyVersion") {
force = true
}

compile "io.moquette:moquette-broker:$moquetteVersion"
}

// Load version properties file and use same version as source code
Expand All @@ -42,4 +44,4 @@ distributions {
}
}
}
}
}
Loading

0 comments on commit 6245995

Please sign in to comment.