This page last changed on Jun 17, 2011 by marimon.

Congratulations, I am surprised with Openremote.
I am a vocational teacher, and I am wondering to teach Openremote to our students.
I would like to know something else about two topics:

  • It's possible any king of user authentication?
  • In UI designer when you put a button, I've seen a navigation action LOGIN and LOGOUT. What those it means? What user/password can I use?
    Thanks.

Yes, authentication is supported through the web container.
It uses the standard mechanism defined by the servlet API and can be configured in the web.xml file and in your container (e.g. tomcat)

Posted by ebariaux at Jun 23, 2011 16:47

Thanks for your answer.
I've been looking for information but I don't understand very well how to do it.
May you tell me some places to look for how to edit web.xml to use authentication?

Posted by marimon at Jun 26, 2011 11:49

Look toward the end of web.xml, where you should several several commented out <security-constraint> elements. Uncomment them. In the simplest case, you can just edit tomcat-users.xml in the Tomcat conf directory to add users with passwords, which will need to have the "openremote" role.

Posted by cortextual at Jul 01, 2011 18:37

Thanks, I did what you said and I got what I need.
If somebody needs a sample of configuration changes I can show it.
Thanks.

Posted by marimon at Jul 04, 2011 09:37

Sample configuration and documentation is most welcome.

Can post it here or create a separate wiki page to explain it.

Posted by admin at Jul 05, 2011 10:59

Sample configuration:
CONFIGURATION CHANGES TO USE USERS AND PASSWORDS.

1. Uncomment "SECURITY CONFIGURATION" at the end of the file web.xml (...\webapps\controller\WEB-INF):


  <security-constraint>
      <web-resource-collection>
        <web-resource-name>Control command RESTful service of Openremote Controller</web-resource-name>
        <description>Control command RESTful service of Openremote Controller</description>
        <url-pattern>/rest/control/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint>
        <role-name>openremote</role-name>
      </auth-constraint>
    </security-constraint>
  

  <!-- Constraint resource: /rest/panel/* -->
  
    <security-constraint>
      <web-resource-collection>
        <web-resource-name>Panel identity RESTful service of Openremote Controller</web-resource-name>
        <description>Panel identity RESTful service of Openremote Controller</description>
        <url-pattern>/rest/panel/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint>
        <role-name>openremote</role-name>
      </auth-constraint>
    </security-constraint>
  

  
   <security-constraint>
     <web-resource-collection>
       <web-resource-name>Status command RESTful service of Openremote Controller</web-resource-name>
       <description>Status command RESTful service of Openremote Controller</description>
       <url-pattern>/rest/status/*</url-pattern>
       <http-method>GET</http-method>
       <http-method>POST</http-method>
     </web-resource-collection>
     <auth-constraint>
       <role-name>openremote</role-name>
     </auth-constraint>
   </security-constraint>
   <security-constraint>
     <web-resource-collection>
       <web-resource-name>Polling command RESTful service of Openremote Controller</web-resource-name>
       <description>Polling command RESTful service of Openremote Controller</description>
       <url-pattern>/rest/polling/*</url-pattern>
       <http-method>GET</http-method>
       <http-method>POST</http-method>
     </web-resource-collection>
     <auth-constraint>
       <role-name>openremote</role-name>
     </auth-constraint>
   </security-constraint>
  

  
    <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>OPENREMOTE_Controller</realm-name>
    </login-config>
    <security-role>
      <role-name>openremote</role-name>
    </security-role>

2. Edit users.xml file (...\security):


<tomcat-users>
  <role rolename="openremote"/>
  <user username="openremote" password="Tomcat" roles="openremote"/>
</tomcat-users>

You can create diferent users, with their own password and assign the role: openremote.

This way use plain text passwords, but I know that there are others ways to encode passwords (digesting user passwords (SHA, MD2 or MD5)). I am going to try but now I do not know how to do.

Posted by marimon at Jul 05, 2011 12:43

Thanks.

Posted by admin at Jul 06, 2011 08:47

Hi Jordi,

I tried the settings you mention and it works, but it requests a password to the user to access the server anyway.

Could you explain in which cases you use this configuration? How the Login option at Navigation is used?

I'm trying to prompt the user a password to access a particular screen, ie a security screen where you can activate the alarm, close valves, etc.., but for the rest not.

Any suggestions?

Thanx!

Posted by aamo at Feb 13, 2012 08:24

There is currently no way to limit access to a particular screen, only to a particular panel.
Once the UI is defined, you should "replicate" the UI from one panel to the other and remove the screen that should be protected.

There are ways to make this replication much easier than I would seem.
Unfortunately, I've discovered that a few bugs in the modeler make those difficult / impossible for now.
As soon as a new version of the modeler is online with fixes to those, I'll post back here and explain a bit more how this works.

Posted by ebariaux at Feb 15, 2012 12:10

Hi Eric,

I have one question. How to specify particular password for particular panel?

Thanks for the help.

Regards,
Nejc

Posted by nejc at Jun 07, 2012 10:25

What you can do is have 2 different users, assign a specific role to each user and protect each panel access with a different role.

Protect the panels like this

<security-constraint>
<web-resource-collection>
<web-resource-name>Panel identity RESTful service of Openremote Controller</web-resource-name>
<description>Panel identity RESTful service of Openremote Controller</description>
<url-pattern>/rest/panel/panel1</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>panel1role</role-name>
</auth-constraint>
</security-constraint>

<security-constraint>
<web-resource-collection>
<web-resource-name>Panel identity RESTful service of Openremote Controller</web-resource-name>
<description>Panel identity RESTful service of Openremote Controller</description>
<url-pattern>/rest/panel/panel2</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>panel2role</role-name>
</auth-constraint>
</security-constraint>

Define the 2 roles

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>OPENREMOTE_Controller</realm-name>
</login-config>
<security-role>
<role-name>panel1role</role-name>
<role-name>panel2role</role-name>
</security-role>

Then in the tomcat users definition, create user1 with panel1role and user2 with panel2role.

Posted by ebariaux at Jun 08, 2012 09:25

Eric, thanks for your explanation of Panel identity part in Security Configuration.

Now I would like to find out a bit more about Control, Status and Polling command part. In which case they can be used?

Thanks again for your explanation.

Regards,
Nejc

Posted by nejc at Sep 27, 2012 11:24

Hello,

I use open remote to control a chacon devices with my raspberry for that I develop my protocol with a 433 Mhz transmitter.

I installed on my raspberry applications:
-Controller
-WebConsole (to use the application when I do not go through a smartphone)
-Designer (to add the xml file protocol HomeEasy)
-Beehive (to synchronize Designer with Controller)

All applications work fine, I created my user with the Designer, I enabled the mail...

The only problem is authentication on the controller, it does not know the database defined in the Designer and Beehive. Authentication is done with tags defined in the web.xml (login-config, etc ...)

But now that it passes through the tomcat-users.xml file.

Someone there is an implementation of "org.apache.catalina.Realm" to connect with the login password defined in the Designer?

If this is not the case, I start

Thanks

Posted by marco93 at May 29, 2013 10:05

Tomcat Realm and Designer authentication are not connected. The Tomcat realm is used for authenticating between the panel and controller (HTTP request authentication). The authentication between controller and designer is done by entering your usename/password on the controller home page http://localhost:8080/controller

HTH

Posted by juha at May 29, 2013 10:19

yes, I think I explained wrong, my English is bad

I would use the login and password recorded in the designer to use between the panel and the controller.

Posted by marco93 at May 29, 2013 10:27

use Designer authentication with http resquest authentication for web service rest

Posted by marco93 at May 29, 2013 10:56

The REST security configuration is explained in this thread: controller2.0.1 user name password set up

You will need to set up the /security/user.xml as such:


<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="openremote"/>
  <user username="test" password="tomcat" roles="openremote"/>
</tomcat-users>

HTH

Posted by juha at May 29, 2013 12:21

Yes it's work fine to add tomcat users, it's work fine

It is necessary to add this information to a file.

What I want install the applications on the raspberry.

After, it isn't me to using the application, but a user.

And even when it is easier for the user to register the designer and use the same account for web services.

User has no computer knowledge.

Posted by marco93 at May 29, 2013 12:32

I suppose you could add a small tool or web script in your RPi that generates/modifies this file.

Posted by juha at May 29, 2013 12:36

yes, it's a solution or implement "org.apache.catalina.Realm" to call a service controller to call database information.

I think both solutions to see what suits me best.

If you are interested, I can make a return.

Posted by marco93 at May 29, 2013 12:46

Yes, do let us know what you find and how you decided to solve it.

Posted by juha at May 29, 2013 13:21

I realized an implementation that allows for an authenticated without informing the "tomcat-users.xml" file connection.
The proposed solution is useful in some cases but not all:
• Interesting to not fill in the login and password in the tomcat-users file
• Interesting when a designer and beehive applications installed on its own domain and we do not use the external application https://composer.openremote.org/demo

Operation to the connection to the controller, the implementation of authentication Realm will perform a http call on the beehive application using the login and password provided by the user if the beehive application returns an HTTP code 200, this means that the user exists and then opens the connection.

Small precision:
• The url used is that used by beehive to retrieve the file openremote.zip
• If the connection is successful, the login and password is specified in a map, it can not make another http call. (Of course it is stored in memory and this information is lost every time to shutdown tomcat)

How to use:
• Put a context.xml file in the application controller:

<?xml version='1.0' encoding='utf-8'?>
<Context>
	<Realm className="fr.ms.raspberry.openremote.controller.catalina.realm.ControllerAuthRealm"/>
</Context>

• Place the jar containing the implementation in the "catalina.home\lib" or "catalina.base\lib" directory (if your tomcat specifies the directory in the file catalina.properties)

That's it.

The URL used to communicate with the rest service beehive is: http://localhost:8080/beehive/rest/
If you want to change you can add in the context.xml file

Example:

<?xml version='1.0' encoding='utf-8'?>
<Context>
	<Realm className="fr.ms.raspberry.openremote.controller.catalina.realm.ControllerAuthRealm" urlRestBeehive=""http://localhost:8080/beehive/rest/super/"/>
</Context>

Here is the url of the jar: http://dl.free.fr/mpexKysc3
PS: This is an implementation made a few minutes, it is not very complicated, if you are in case you do not have an instance of the application "designer" and "beehive", this solution isn't appropriate because it would open access to your controller to anyone who has an account on Designer "https://composer.openremote.org/demo." The solution would be interesting is to inquire into the Realm implementation, the user at the time of synchronization between the beehive and the controller. As only the user has synchronized the controller can connect to the service rest of the application.

Here's the implementation:

package fr.ms.raspberry.openremote.controller.catalina.realm;

import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.realm.RealmBase;
import org.apache.catalina.util.Base64;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;

public class ControllerAuthRealm extends RealmBase
{

    private static Log log = LogFactory.getLog(ControllerAuthRealm.class);

    private static final String NAME = "ControllerAuthRealm";

    private static final String ROLE = "openremote";

    private final Map<String, Principal> principals = Collections
            .synchronizedMap(new HashMap<String, Principal>());

    private String urlRestBeehive = "http://localhost:8080/beehive/rest/";

    @Override
    protected String getName()
    {
        return NAME;
    }

    @Override
    protected String getPassword(String username)
    {
        username = username.trim();

        final GenericPrincipal principal = (GenericPrincipal) principals
                .get(username);

        if (principal != null)
        {
            return principal.getPassword();
        }
        else
        {
            return null;
        }
    }

    @Override
    protected Principal getPrincipal(String username)
    {
        username = username.trim();

        return principals.get(username);
    }

    @Override
    public Principal authenticate(String username, String credentials)
    {
        username = username.trim();
        credentials = credentials.trim();

        Principal principal = getPrincipal(username);

        if (principal == null)
        {
            synchronized (this) {
                principal = getPrincipal(username);
                if (principal == null)
                {
                    principal = checkUser(username, credentials);
                    if (principal != null)
                    {
                        log.info("Ajout d'un nouvel utilisateur : " + username);
                        principals.put(username, principal);
                    }
                }
            }
        }
        return principal;
    }

    public final static String HTTP_AUTHORIZATION_HEADER = "Authorization";

    public final static String HTTP_BASIC_AUTHORIZATION = "Basic ";

    private final static String BEEHIVE_REST_USER_DIR = "user";

    private final static String BEEHIVE_REST_OPENREMOTE_ZIP = "openremote.zip";

    private Principal checkUser(final String username, final String password)
    {
        log.info("username : " + username + " - password : " + password);
        if (username.length() == 0 || password.length() == 0)
        {
            return null;
        }

        try
        {
            final String httpURI = BEEHIVE_REST_USER_DIR + "/" + username + "/"
                    + BEEHIVE_REST_OPENREMOTE_ZIP;

            final URL beehiveBaseURL = new URL(urlRestBeehive);
            final URI beehiveUserURI = beehiveBaseURL.toURI().resolve(httpURI);

            log.info("url : " + beehiveUserURI);
            final URLConnection connection = beehiveUserURI.toURL()
                    .openConnection();

            if (!(connection instanceof HttpURLConnection))
            {
                throw new ConnectException("The ''" + BEEHIVE_REST_USER_DIR
                        + "'' property ''" + urlRestBeehive
                        + "'' must be a URL with http:// schema.");
            }

            final HttpURLConnection http = (HttpURLConnection) connection;

            http.setDoInput(true);
            http.setRequestMethod("GET");

            final String encodePassword = encode(username, password);
            final String authString = username + ":" + encodePassword;
            final byte[] authEncBytes = Base64.encode(authString.getBytes());

            final String basicAuthn = new String(authEncBytes);
            http.addRequestProperty(HTTP_AUTHORIZATION_HEADER,
                    HTTP_BASIC_AUTHORIZATION + basicAuthn);

            http.connect();

            final int response = http.getResponseCode();

            log.info("Http Code Beehive : " + response);

            switch (response)
            {
            case HttpURLConnection.HTTP_OK:
                final List<String> roles = new ArrayList<String>();
                roles.add(ROLE);
                final GenericPrincipal principal = new GenericPrincipal(
                        this, username, password, roles);
                return principal;
            }

            return null;
        } catch (final Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    private static String encode(final String username, final String password)
    {
        final String concat = password + "{" + username + "}";
        final String md5Hex = MD5Hex(concat);
        return md5Hex;
    }

    public static String MD5Hex(final String s)
    {
        String result = null;
        try
        {
            final MessageDigest md5 = MessageDigest.getInstance("MD5");
            final byte[] digest = md5.digest(s.getBytes("UTF-8"));
            result = toHex(digest);
        } catch (final Exception e)
        {
            throw new RuntimeException(e);
        }
        return result;
    }

    public static String toHex(final byte[] a)
    {
        final StringBuilder sb = new StringBuilder(a.length * 2);
        for (final byte element : a)
        {
            sb.append(Character.forDigit((element & 0xf0) >> 4, 16));
            sb.append(Character.forDigit(element & 0x0f, 16));
        }
        return sb.toString();
    }

    public void setUrlRestBeehive(final String urlRestBeehive) {
        this.urlRestBeehive = urlRestBeehive;
    }
}
Posted by marco93 at Jun 10, 2013 13:51

You have to put code int {code}...{code} tags.

Posted by mredeker at Jun 11, 2013 08:08

Hi Jordi, you mentioned that you considered teaching to your students. Did you have anything specific in mind?

Posted by pierre kil at Jun 12, 2013 13:04

Marco,

Thank you for sharing your implementation.

Best regards,

– Juha

Posted by juha at Jun 19, 2013 15:12
Document generated by Confluence on Jun 05, 2016 09:32