Plugin development for authentication

Submitted by Anonymous on Wed, 2007-08-29 23:34.

Hi there. Awesome project. I've been trying to figure out how to write a plugin for authentication from an external pool of data.

I saw the instructions on how to write plugins, however I'm still lost as to where in the code I should stick the authentication module. I see in the config xml file where to load the plugin.

I would love for someone to point me in the right direction with some specific info on how to achieve the authentication plugin.

Thanks,
Mark

Trackback URL for this post:

http://www.tigase.org/en/trackback/1324
kobit's picture
Submitted by kobit on Tue, 2007-10-30 22:05.

> I see that the UserAuthRepositoryImpl relies on an
> UserRepository instance. I can see an example in
> JDBCRepository and I see that at initialisation it
> creates a database connection.

Yes, indeed. UserAuthRepositoryImpl is simplified authentication module assuming all account data is kept in main user repository. Thus it uses UserRepository. Actually this is a case for many installations.

> Do I need to get the database connection from a
> pool of connections?

Normally you don't need pool of connections. Tigase opens very few database connections and keeps it (them) open all the time. All transactions are executed on the same connection unless it is closed by database server. It should be then reopened which is done by checkConnection() method in my classes.

> Is Tigase trying to authenticate more than one user
> at a time?

If you are asking whether the database connection can be used concurrently by many threads that I say No. Tigase is designed and implemented to use database by a single thread only. If more than 1 thread needs access to database then another connection is opened. But this may happen in very extreme configurations only like when you create many SessionManagers in your server.

No concurrent calls to database on the same connection. But of course more than one user can be authenticated at a time as authentication may consists of many steps - client requests, server responses like in SASL for example. Assuming 10 users connects to the server at the same time, they will try to authenticate at the same time. But database calls needed for authentication will be called one-by-one for each user, no concurrent calls.

I hope this answer your question, if not please ask more!


Submitted by Anonymous (not verified) on Tue, 2007-10-30 21:49.

I see that the UserAuthRepositoryImpl relies on an UserRepository instance. I can see an example in JDBCRepository and I see that at initialisation it creates a database connection.

Do I need to get the database connection from a pool of connections? Is Tigase trying to authenticate more than one user at a time?

kobit's picture
Submitted by kobit on Thu, 2007-09-13 09:37.

I think the change was only in MessageRouterConfig.java file. I work also on Bosh implementation so those files might be changed as well but it shouldn't affect anything except Bosh.
You can update your sources using command:

svn up

Submitted by Johnny (not verified) on Wed, 2007-09-12 19:39.

What files have the changes for --comp-name muc --comp-class tigase.muc.MUCService?

kobit's picture
Submitted by kobit on Wed, 2007-09-12 11:38.

Ah, I am sorry. It is my fault. Very old version of MUC was publicly available and that version is not compatible with current Tigase server API.

Please download the latest snapshot 0.1.5 published today and everything should work fine.

And you have to revert back to tigase.muc.MUCService class as the old MUC used different packages from current version.

And yes, if you want to use --comp-name muc --comp-class tigase.muc.MUCService you need to checkout the last SVN code.


Submitted by Johnny (not verified) on Tue, 2007-09-11 23:05.

Okay I already have tigase-muc-0.1.1-20070530.103942-2.jar in the libs dir and also have it in my class path. At first it doesn't run and complains that tigase.muc.MUCService not found. So I change tigase.muc.MUCService to org.tigase.muc.MUCService in the tigase-config.xml then it seems to run fine. However when a client connects it throws some exceptions:

2007-09-11 22:12:43 AbstractMessageReceiver$QueueListener.run() SEVERE: Except
ion during packet processing: java.lang.NullPointerException
at java.util.LinkedList.addAll(Unknown Source)
at java.util.LinkedList.addAll(Unknown Source)
at org.tigase.muc.MUCService.processPacket(MUCService.java:190)
at tigase.server.AbstractMessageReceiver$QueueListener.run(AbstractMessa
geReceiver.java:391)
at java.lang.Thread.run(Unknown Source)

unknown stanza S2S - not delivered
2007-09-11 22:12:43 AbstractMessageReceiver$QueueListener.run() SEVERE: Except
ion during packet processing: java.lang.NullPointerException
at java.util.LinkedList.addAll(Unknown Source)
at java.util.LinkedList.addAll(Unknown Source)
at org.tigase.muc.MUCService.processPacket(MUCService.java:190)
at tigase.server.AbstractMessageReceiver$QueueListener.run(AbstractMessa
geReceiver.java:391)
at java.lang.Thread.run(Unknown Source)

Also, I need to download your new code changes for this --comp-name muc --comp-class tigase.muc.MUCService?

Thanks

kobit's picture
Submitted by kobit on Tue, 2007-09-11 22:16.

XML config file attached below.
It works for me. Hopefully will work for you too.

I have also slightly modified Tigase code to make this easier for you and other people wanting to add components without too much hassle....

You now don't need any Jabber/XMPP client or anything...

Just put following parameters to Tigase when starting the server:
--comp-name muc --comp-class tigase.muc.MUCService

... assuming you have muc jar file in libs/ directory...

Please note, it will work only if config file does not exist yet. It may not work if the config file exist.
And actually it works only for the version which is in SVN repository yet but it seems to me you already use version from repository.

Of course you can use any component name and any component
class. It works not only for MUC but for all valid Tigase components.

I hope this helps, if you have any more questions please let me know.

Ah, and to be able to test this I have replaced your repository classes with XMLRepository so you have to edit the XML file and put your classes back there....

<?xml version='1.0' encoding='UTF-8'?>

<tigase-config>
 <component name="basic-conf">
  <map>
   <entry key="demo-mode" type="Boolean" value="false"/>
  </map>
  <node name="logging">
   <map>
    <entry key=".level" type="String" value="INFO"/>
    <entry key="handlers" type="String" value="java.util.logging.ConsoleHandler+java.util.logging.FileHandler"/>
    <entry key="java.util.logging.ConsoleHandler.formatter" type="String" value="tigase.util.LogFormatter"/>
    <entry key="java.util.logging.ConsoleHandler.level" type="String" value="INFO"/>
    <entry key="java.util.logging.FileHandler.append" type="String" value="true"/>
    <entry key="java.util.logging.FileHandler.count" type="String" value="5"/>
    <entry key="java.util.logging.FileHandler.formatter" type="String" value="tigase.util.LogFormatter"/>
    <entry key="java.util.logging.FileHandler.level" type="String" value="INFO"/>
    <entry key="java.util.logging.FileHandler.limit" type="String" value="10000000"/>
    <entry key="java.util.logging.FileHandler.pattern" type="String" value="logs%2Ftigase.log"/>
    <entry key="java.util.logging.level" type="String" value="INFO"/>
    <entry key="tigase.useParentHandlers" type="String" value="true"/>
   </map>
  </node>
 </component>
 <component name="bosh">
  <map>
   <entry key="concurrent-requests" type="Integer" value="2"/>
   <entry key="hold-requests" type="Integer" value="1"/>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-inactivity" type="Long" value="120"/>
   <entry key="max-queue-size" type="Integer" value="1000"/>
   <entry key="max-wait" type="Long" value="60"/>
   <entry key="min-polling" type="Long" value="10"/>
   <entry key="def-hostname" type="String" value="localhost"/>
  </map>
  <node name="connections">
   <map>
    <entry key="ports" type="int[]">
     <item value="5280"/>
    </entry>
   </map>
   <node name="5280">
    <map>
     <entry key="ifc" type="String[]">
      <item value="*"/>
     </entry>
     <entry key="remote-host" type="String" value="localhost"/>
     <entry key="socket" type="String" value="plain"/>
     <entry key="type" type="String" value="accept"/>
    </map>
    <node name="tls">
     <map>
      <entry key="required" type="Boolean" value="false"/>
     </map>
    </node>
   </node>
   <node name="tls">
    <map>
     <entry key="def-cert-alias" type="String" value="default"/>
     <entry key="keys-store" type="String" value="certs/rsa-keystore"/>
     <entry key="keys-store-password" type="String" value="keystore"/>
     <entry key="trusts-store" type="String" value="certs/truststore"/>
     <entry key="trusts-store-password" type="String" value="truststore"/>
     <entry key="use" type="Boolean" value="true"/>
    </map>
   </node>
  </node>
  <node name="routings">
   <map>
    <entry key=".+" type="String" value="sess-man%40localhost"/>
    <entry key="multi-mode" type="Boolean" value="true"/>
   </map>
  </node>
 </component>
 <component name="c2s">
  <map>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-queue-size" type="Integer" value="1000"/>
   <entry key="def-hostname" type="String" value="localhost"/>
  </map>
  <node name="connections">
   <map>
    <entry key="ports" type="int[]">
     <item value="5222"/>
     <item value="5223"/>
    </entry>
   </map>
   <node name="5222">
    <map>
     <entry key="ifc" type="String[]">
      <item value="*"/>
     </entry>
     <entry key="remote-host" type="String" value="localhost"/>
     <entry key="socket" type="String" value="plain"/>
     <entry key="type" type="String" value="accept"/>
    </map>
    <node name="tls">
     <map>
      <entry key="required" type="Boolean" value="false"/>
     </map>
    </node>
   </node>
   <node name="5223">
    <map>
     <entry key="ifc" type="String[]">
      <item value="*"/>
     </entry>
     <entry key="remote-host" type="String" value="localhost"/>
     <entry key="socket" type="String" value="ssl"/>
     <entry key="type" type="String" value="accept"/>
    </map>
    <node name="tls">
     <map>
      <entry key="required" type="Boolean" value="false"/>
     </map>
    </node>
   </node>
   <node name="tls">
    <map>
     <entry key="def-cert-alias" type="String" value="default"/>
     <entry key="keys-store" type="String" value="certs%2Frsa-keystore"/>
     <entry key="keys-store-password" type="String" value="keystore"/>
     <entry key="trusts-store" type="String" value="certs%2Ftruststore"/>
     <entry key="trusts-store-password" type="String" value="truststore"/>
     <entry key="use" type="Boolean" value="true"/>
    </map>
   </node>
  </node>
  <node name="routings">
   <map>
    <entry key=".+" type="String" value="sess-man%40jngo-e510"/>
    <entry key="multi-mode" type="Boolean" value="true"/>
   </map>
  </node>
 </component>
 <component name="message-router">
  <map>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-queue-size" type="Integer" value="1000"/>
   <entry key="def-hostname" type="String" value="localhost"/>
  </map>
  <node name="components">
   <map/>
   <node name="msg-receivers">
    <map>
     <entry key="bosh.active" type="Boolean" value="true"/>
     <entry key="bosh.class" type="String" value="tigase.server.bosh.BoshConnectionManager"/>
     <entry key="c2s.active" type="Boolean" value="true"/>
     <entry key="c2s.class" type="String" value="tigase.server.xmppclient.ClientConnectionManager"/>
     <entry key="id-names" type="String[]">
      <item value="bosh"/>
      <item value="muc"/>
      <item value="c2s"/>
      <item value="s2s"/>
      <item value="sess-man"/>
     </entry>
     <entry key="s2s.active" type="Boolean" value="true"/>
     <entry key="s2s.class" type="String" value="tigase.server.xmppserver.ServerConnectionManager"/>
     <entry key="sess-man.active" type="Boolean" value="true"/>
     <entry key="sess-man.class" type="String" value="tigase.server.xmppsession.SessionManager"/>
     <entry key="muc.active" type="Boolean" value="true"/>
     <entry key="muc.class" type="String" value="tigase.muc.MUCService"/>
    </map>
   </node>
   <node name="registrators">
    <map>
     <entry key="id-names" type="String[]">
      <item value="stat-1"/>
     </entry>
     <entry key="stat-1.active" type="Boolean" value="true"/>
     <entry key="stat-1.class" type="String" value="tigase.stats.StatisticsCollector"/>
    </map>
   </node>
  </node>
 </component>
 <component name="s2s">
  <map>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-packet-waiting-time" type="Long" value="300000"/>
   <entry key="max-queue-size" type="Integer" value="1000"/>
   <entry key="def-hostname" type="String" value="localhost"/>
  </map>
  <node name="connections">
   <map>
    <entry key="ports" type="int[]">
     <item value="5269"/>
    </entry>
   </map>
   <node name="5269">
    <map>
     <entry key="ifc" type="String[]">
      <item value="*"/>
     </entry>
     <entry key="remote-host" type="String" value="localhost"/>
     <entry key="socket" type="String" value="plain"/>
     <entry key="type" type="String" value="accept"/>
    </map>
    <node name="tls">
     <map>
      <entry key="required" type="Boolean" value="false"/>
     </map>
    </node>
   </node>
   <node name="tls">
    <map>
     <entry key="def-cert-alias" type="String" value="default"/>
     <entry key="keys-store" type="String" value="certs%2Frsa-keystore"/>
     <entry key="keys-store-password" type="String" value="keystore"/>
     <entry key="trusts-store" type="String" value="certs%2Ftruststore"/>
     <entry key="trusts-store-password" type="String" value="truststore"/>
     <entry key="use" type="Boolean" value="true"/>
    </map>
   </node>
  </node>
 </component>
 <component name="sess-man">
  <map>
   <entry key="admins" type="String[]">
    <item value="admin%40jngo-e510"/>
    <item value="admin%40localhost"/>
    <item value="test%40localhost"/>
    <item value="dev1%40localhost"/>
   </entry>
   <entry key="user-repo-class" type="String" value="tigase.db.xml.XMLRepository"/>
   <entry key="user-repo-url" type="String" value="user-repository.xml"/>
   <entry key="auth-repo-class" type="String" value="tigase.db.xml.XMLRepository"/>
   <entry key="auth-repo-url" type="String" value="user-repository.xml"/>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-queue-size" type="Integer" value="1000"/>
   <entry key="plugins" type="String[]">
    <item value="http%3A%2F%2Fjabber.org%2Fprotocol%2Fcommands"/>
    <item value="http%3A%2F%2Fjabber.org%2Fprotocol%2Fstats"/>
    <item value="jabber%3Aiq%3Aauth"/>
    <item value="jabber%3Aiq%3Aprivacy"/>
    <item value="jabber%3Aiq%3Aprivate"/>
    <item value="jabber%3Aiq%3Aregister"/>
    <item value="jabber%3Aiq%3Aroster"/>
    <item value="jabber%3Aiq%3Aversion"/>
    <item value="msgoffline"/>
    <item value="presence"/>
    <item value="starttls"/>
    <item value="urn%3Aietf%3Aparams%3Axml%3Ans%3Axmpp-bind"/>
    <item value="urn%3Aietf%3Aparams%3Axml%3Ans%3Axmpp-sasl"/>
    <item value="urn%3Aietf%3Aparams%3Axml%3Ans%3Axmpp-session"/>
    <item value="urn%3Axmpp%3Aping"/>
    <item value="vcard-temp"/>
   </entry>
   <entry key="def-hostname" type="String" value="localhost"/>
  </map>
 </component>
 <component name="muc">
  <map>
   <entry key="def-hostname" type="String" value="test-d"/>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="muc.localhost"/>
   </entry>
   <entry key="max-queue-size" type="Integer" value="1000"/>
   <entry key="muc-repo-class" type="String" value="tigase.db.xml.XMLRepository"/>
   <entry key="muc-repo-url" type="String" value="user-repository.xml"/>
  </map>
 </component>
</tigase-config>

Submitted by Johnny (not verified) on Tue, 2007-09-11 18:15.

1. I also tried PSI, it didnt work well on Windows and behave weirdly. I'll try Coccinella
2. I'm running tigase on my local machine so I'm unable to give you access. So I guess I could send you the config.xml file :) Can I contact you via email? My email is jngo AT gaiaonline.com. In case you don't want to communicate via email; this is my full tigase-config.xml:

<?xml version='1.0' encoding='UTF-8'?>

<tigase-config>
 <component name="basic-conf">
  <map>
   <entry key="demo-mode" type="Boolean" value="false"/>
  </map>
  <node name="logging">
   <map>
    <entry key=".level" type="String" value="INFO"/>
    <entry key="handlers" type="String" value="java.util.logging.ConsoleHandler+java.util.logging.FileHandler"/>
    <entry key="java.util.logging.ConsoleHandler.formatter" type="String" value="tigase.util.LogFormatter"/>
    <entry key="java.util.logging.ConsoleHandler.level" type="String" value="INFO"/>
    <entry key="java.util.logging.FileHandler.append" type="String" value="true"/>
    <entry key="java.util.logging.FileHandler.count" type="String" value="5"/>
    <entry key="java.util.logging.FileHandler.formatter" type="String" value="tigase.util.LogFormatter"/>
    <entry key="java.util.logging.FileHandler.level" type="String" value="INFO"/>
    <entry key="java.util.logging.FileHandler.limit" type="String" value="10000000"/>
    <entry key="java.util.logging.FileHandler.pattern" type="String" value="logs%2Ftigase.log"/>
    <entry key="java.util.logging.level" type="String" value="INFO"/>
    <entry key="tigase.useParentHandlers" type="String" value="true"/>
   </map>
  </node>
 </component>
 <component name="bosh">
  <map>
   <entry key="concurrent-requests" type="Integer" value="2"/>
   <entry key="hold-requests" type="Integer" value="1"/>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-inactivity" type="Long" value="120"/>
   <entry key="max-queue-size" type="Integer" value="1000"/>
   <entry key="max-wait" type="Long" value="60"/>
   <entry key="min-polling" type="Long" value="10"/>
  </map>
  <node name="connections">
   <map>
    <entry key="ports" type="int[]">
     <item value="5280"/>
    </entry>
   </map>
   <node name="5280">
    <map>
     <entry key="ifc" type="String[]">
      <item value="*"/>
     </entry>
     <entry key="remote-host" type="String" value="localhost"/>
     <entry key="socket" type="String" value="plain"/>
     <entry key="type" type="String" value="accept"/>
    </map>
    <node name="tls">
     <map>
      <entry key="required" type="Boolean" value="false"/>
     </map>
    </node>
   </node>
   <node name="tls">
    <map>
     <entry key="def-cert-alias" type="String" value="default"/>
     <entry key="keys-store" type="String" value="certs%5Crsa-keystore"/>
     <entry key="keys-store-password" type="String" value="keystore"/>
     <entry key="trusts-store" type="String" value="certs%5Ctruststore"/>
     <entry key="trusts-store-password" type="String" value="truststore"/>
     <entry key="use" type="Boolean" value="true"/>
    </map>
   </node>
  </node>
 </component>
 <component name="c2s">
  <map>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-queue-size" type="Integer" value="1000"/>
  </map>
  <node name="connections">
   <map>
    <entry key="ports" type="int[]">
     <item value="5222"/>
     <item value="5223"/>
    </entry>
   </map>
   <node name="5222">
    <map>
     <entry key="ifc" type="String[]">
      <item value="*"/>
     </entry>
     <entry key="remote-host" type="String" value="localhost"/>
     <entry key="socket" type="String" value="plain"/>
     <entry key="type" type="String" value="accept"/>
    </map>
    <node name="tls">
     <map>
      <entry key="required" type="Boolean" value="false"/>
     </map>
    </node>
   </node>
   <node name="5223">
    <map>
     <entry key="ifc" type="String[]">
      <item value="*"/>
     </entry>
     <entry key="remote-host" type="String" value="localhost"/>
     <entry key="socket" type="String" value="ssl"/>
     <entry key="type" type="String" value="accept"/>
    </map>
    <node name="tls">
     <map>
      <entry key="required" type="Boolean" value="false"/>
     </map>
    </node>
   </node>
   <node name="tls">
    <map>
     <entry key="def-cert-alias" type="String" value="default"/>
     <entry key="keys-store" type="String" value="certs%5Crsa-keystore"/>
     <entry key="keys-store-password" type="String" value="keystore"/>
     <entry key="trusts-store" type="String" value="certs%5Ctruststore"/>
     <entry key="trusts-store-password" type="String" value="truststore"/>
     <entry key="use" type="Boolean" value="true"/>
    </map>
   </node>
  </node>
  <node name="routings">
   <map>
    <entry key=".+" type="String" value="sess-man%40jngo-e510"/>
    <entry key="multi-mode" type="Boolean" value="true"/>
   </map>
  </node>
 </component>
 <component name="message-router">
  <map>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-queue-size" type="Integer" value="1000"/>
  </map>
  <node name="components">
   <map/>
   <node name="msg-receivers">
    <map>
     <entry key="bosh.active" type="Boolean" value="true"/>
     <entry key="bosh.class" type="String" value="tigase.server.bosh.BoshConnectionManager"/>
     <entry key="c2s.active" type="Boolean" value="true"/>
     <entry key="c2s.class" type="String" value="tigase.server.xmppclient.ClientConnectionManager"/>
     <entry key="id-names" type="String[]">
      <item value="bosh"/>
      <item value="c2s"/>
      <item value="s2s"/>
      <item value="sess-man"/>
     </entry>
     <entry key="s2s.active" type="Boolean" value="true"/>
     <entry key="s2s.class" type="String" value="tigase.server.xmppserver.ServerConnectionManager"/>
     <entry key="sess-man.active" type="Boolean" value="true"/>
     <entry key="sess-man.class" type="String" value="tigase.server.xmppsession.SessionManager"/>
    </map>
   </node>
   <node name="registrators">
    <map>
     <entry key="id-names" type="String[]">
      <item value="stat-1"/>
     </entry>
     <entry key="stat-1.active" type="Boolean" value="true"/>
     <entry key="stat-1.class" type="String" value="tigase.stats.StatisticsCollector"/>
    </map>
   </node>
  </node>
 </component>
 <component name="s2s">
  <map>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-packet-waiting-time" type="Long" value="300000"/>
   <entry key="max-queue-size" type="Integer" value="1000"/>
  </map>
  <node name="connections">
   <map>
    <entry key="ports" type="int[]">
     <item value="5269"/>
    </entry>
   </map>
   <node name="5269">
    <map>
     <entry key="ifc" type="String[]">
      <item value="*"/>
     </entry>
     <entry key="remote-host" type="String" value="localhost"/>
     <entry key="socket" type="String" value="plain"/>
     <entry key="type" type="String" value="accept"/>
    </map>
    <node name="tls">
     <map>
      <entry key="required" type="Boolean" value="false"/>
     </map>
    </node>
   </node>
   <node name="tls">
    <map>
     <entry key="def-cert-alias" type="String" value="default"/>
     <entry key="keys-store" type="String" value="certs%5Crsa-keystore"/>
     <entry key="keys-store-password" type="String" value="keystore"/>
     <entry key="trusts-store" type="String" value="certs%5Ctruststore"/>
     <entry key="trusts-store-password" type="String" value="truststore"/>
     <entry key="use" type="Boolean" value="true"/>
    </map>
   </node>
  </node>
 </component>
 <component name="sess-man">
  <map>
   <entry key="admins" type="String[]">
    <item value="admin%40jngo-e510"/>
    <item value="admin%40localhost"/>
	<item value="dev1%40localhost"/>
   </entry>
   <entry key="auth-repo-class" type="String" value="com.johnny.jabber.tigase.JohnnyUserAuthRepository"/>
   <entry key="auth-repo-url" type="String" value=""/>
   <entry key="hostnames" type="String[]">
    <item value="jngo-e510"/>
    <item value="localhost"/>
   </entry>
   <entry key="max-queue-size" type="Integer" value="1000"/>
   <entry key="plugins" type="String[]">
    <item value="http%3A%2F%2Fjabber.org%2Fprotocol%2Fcommands"/>
    <item value="http%3A%2F%2Fjabber.org%2Fprotocol%2Fstats"/>
    <item value="jabber%3Aiq%3Aauth"/>
    <item value="jabber%3Aiq%3Aprivacy"/>
    <item value="jabber%3Aiq%3Aprivate"/>
    <item value="jabber%3Aiq%3Aregister"/>
    <item value="jabber%3Aiq%3Aroster"/>
    <item value="jabber%3Aiq%3Aversion"/>
    <item value="msgoffline"/>
    <item value="presence"/>
    <item value="starttls"/>
    <item value="urn%3Aietf%3Aparams%3Axml%3Ans%3Axmpp-bind"/>
    <item value="urn%3Aietf%3Aparams%3Axml%3Ans%3Axmpp-sasl"/>
    <item value="urn%3Aietf%3Aparams%3Axml%3Ans%3Axmpp-session"/>
    <item value="urn%3Axmpp%3Aping"/>
    <item value="vcard-temp"/>
   </entry>
   <entry key="user-repo-class" type="String" value="com.johnny.jabber.tigase.JohnnyUserRepository"/>
   <entry key="user-repo-url" type="String" value=""/>
  </map>
 </component>
</tigase-config>

Thanks

kobit's picture
Submitted by kobit on Tue, 2007-09-11 08:27.
  1. Yes you are right, the article doesn't mention MUC specifically. It is about adding components in general. But if it worked in your client you wouldn't have any problems to figure out how to add MUC.
  2. Regarding the client. When I was implementing this a couple of months ago the only client fully supporting ad-hoc commands and service discovery (which is also essential to have all these working) was Psi-0.11 last beta. Coccinella may also support this but I am not 100% sure. Gajim could list all availble ad-hoc commands but only when I used the last version built directly from sources and I could only run the first command. Configuring new component consist of a few commands... None of all other client supported ad-hoc commands and service discovery well enough. This is actually very surprising because service-discovery and ad-hoc commands are very old Jabbber/XMPP extensions...
  3. You don't need to do anything to expose commands to client. You just need to use proper client. Try the last possible version, even Beta or from sources of your favorite client. I know Psi-0.11 supports these well.
  4. The list is quite long and it looks like a tree of service discovery elements. Here is a screenshot from Psi connected to tigase.org: service-discovery.png.
  5. All commands are exposed to everybody who can access the server but execution of some commands is limited to the server admins only. You can setup as many admins for the server as you like. You set admins in XML config file or via config wizards but after that you need also to register/create those accounts on the server.
  6. I am not the author of the MUC component but I am pretty sure configuration for this component is identical regardless it is accessible through XEP-0114 or it runs inside main server. MUC just doesn't know where it is running and it behave the same way so configuration is the same. You can simply use the config above I provided as a reference and example.
  7. Your wish is actually quite simple to fulfill ;-). I probably can not visit you but:
    • If you tell me the address of your Tigase installation I could access it with my Jabbber/XMPP client and help you with configuration settings.
    • You could give me shell access to your Tigase installation and I can help you wit configuration settings.
    • You could tell me all requirements and parameters for your Tigase installation and I could generate XML config file for you and send it over to you ready to use.

Submitted by Johnny (not verified) on Mon, 2007-09-10 21:54.

Hi Kobit,

Sorry for being too slow here. I've read this http://www.tigase.org/node/1265 a couple times already but could not found anything that could answer my question that show me how to config the MUC to run inside my main server.

I'm using a xmpp client call Gajim which also supports ad-hoc command and Service explorer. When I attempt to run a command; it says "This jabber entity does not expose any commands".
http://img178.imageshack.us/img178/9152/gajimserviceexploreraq9.th.jpg

so my questions now are:
1. How to expose commands to the client?
2. What commands should be exposed?
3. How to set who can/cannot access to these commands?
4. You have any config xml file that has the MUC to run inside?
Please advice. I wish you were local here then I could treat you out for helping ;)

kobit's picture
Submitted by kobit on Sun, 2007-09-09 20:58.
  1. I have simple config for a server instance which runs only MUC and external component. So in my installation MUC doesn't run inside main XMPP/Jabber server. It runs as a separate process and connects to the main server via XEP-0114 - external component protocol.
    This is configuration generator file (with passwords and other sensitive data replaced):

    ENC="-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
    DRV="-Djdbc.drivers=com.mysql.jdbc.Driver"
    CLASSPATH="${CLASSPATH}:libs/jdbc-mysql.jar"
    JAVA_OPTIONS="${ENC} ${DRV} -server -Xms100M -Xmx100M "
    TIGASE_CONFIG="etc/tigase-muc.xml"
    TIGASE_OPTIONS="--gen-config-comp --admins \"adm1@tigase.org,adm2@tigase.org\" \
      --user-db mysql \
      --user-db-uri \"jdbc:mysql://localhost/drupal?user=root&password=mypass\" \
      --virt-hosts muc.tigase.org \
      --debug server,muc \
      --comp-name muc --comp-class tigase.muc.MUCService \
      --ext-comp-1 \"muc.tigase.org,tigase.org,5348,muc-passwd,plain,connect\" 

    And this is XML file generated:

    <?xml version='1.0' encoding='UTF-8'?>
    
    <tigase-config>
     <component name="basic-conf">
      <map>
       <entry value="false" type="Boolean" key="demo-mode"/>
      </map>
      <node name="logging">
       <map>
        <entry value="INFO" type="String" key=".level"/>
        <entry value="java.util.logging.ConsoleHandler+java.util.logging.FileHandler" type="String" key="handlers"/>
        <entry value="tigase.util.LogFormatter" type="String" key="java.util.logging.ConsoleHandler.formatter"/>
        <entry value="ALL" type="String" key="java.util.logging.ConsoleHandler.level"/>
        <entry value="true" type="String" key="java.util.logging.FileHandler.append"/>
        <entry value="5" type="String" key="java.util.logging.FileHandler.count"/>
        <entry value="tigase.util.LogFormatter" type="String" key="java.util.logging.FileHandler.formatter"/>
        <entry value="ALL" type="String" key="java.util.logging.FileHandler.level"/>
        <entry value="1000000" type="String" key="java.util.logging.FileHandler.limit"/>
        <entry value="logs%2Ftigase.log" type="String" key="java.util.logging.FileHandler.pattern"/>
        <entry value="ALL" type="String" key="tigase.muc.level"/>
        <entry value="true" type="String" key="tigase.useParentHandlers"/>
        <entry value="ALL" type="String" key="tigase.server.level"/>
       </map>
      </node>
     </component>
     <component name="message-router">
      <map>
       <entry type="String[]" key="hostnames">
        <item value="muc.tigase.org"/>
       </entry>
       <entry value="1000" type="Integer" key="max-queue-size"/>
      </map>
      <node name="components">
       <map/>
       <node name="msg-receivers">
        <map>
         <entry value="true" type="Boolean" key="ext-comp-1.active"/>
         <entry value="tigase.server.xmppcomponent.ComponentConnectionManager" type="String" key="ext-comp-1.class"/>
         <entry type="String[]" key="id-names">
          <item value="muc"/>
          <item value="ext-comp-1"/>
         </entry>
         <entry value="true" type="Boolean" key="muc.active"/>
         <entry value="tigase.muc.MUCService" type="String" key="muc.class"/>
        </map>
       </node>
       <node name="registrators">
        <map>
         <entry type="String[]" key="id-names">
          <item value="stat-1"/>
         </entry>
         <entry value="true" type="Boolean" key="stat-1.active"/>
         <entry value="tigase.stats.StatisticsCollector" type="String" key="stat-1.class"/>
        </map>
       </node>
      </node>
     </component>
     <component name="muc">
      <map>
       <entry type="String[]" key="hostnames">
        <item value="muc.tigase.org"/>
       </entry>
       <entry value="1000" type="Integer" key="max-queue-size"/>
       <entry value="tigase.db.jdbc.JDBCRepository" type="String" key="muc-repo-class"/>
       <entry value="jdbc%3Amysql%3A%2F%2Flocalhost%2Fdrupal%3Fuser%3Droot%26password%3Dmypass" type="String" key="muc-repo-url"/>
      </map>
     </component>
     <component name="ext-comp-1">
      <map>
       <entry value="generic" type="String" key="identity-type"/>
       <entry value="1000" type="Integer" key="max-queue-size"/>
       <entry value="false" type="Boolean" key="pack-routed"/>
       <entry value="true" type="Boolean" key="service-disco"/>
      </map>
      <node name="connections">
       <map>
        <entry type="int[]" key="ports">
         <item value="5348"/>
        </entry>
       </map>
       <node name="5348">
        <map>
         <entry type="String[]" key="ifc">
          <item value="*"/>
         </entry>
         <entry value="muc.tigase.org" type="String" key="local-host"/>
         <entry value="1800000" type="Integer" key="max-reconnects"/>
         <entry value="tigase.org" type="String" key="remote-host"/>
         <entry type="String[]" key="routing-table">
          <item value="*"/>
         </entry>
         <entry value="muc-passwd" type="String" key="secret"/>
         <entry value="plain" type="String" key="socket"/>
         <entry value="connect" type="String" key="type"/>
        </map>
        <node name="tls">
         <map>
          <entry value="false" type="Boolean" key="required"/>
         </map>
        </node>
       </node>
       <node name="tls">
        <map>
         <entry value="default" type="String" key="def-cert-alias"/>
         <entry value="certs%2Frsa-keystore" type="String" key="keys-store"/>
         <entry value="keystore-passwd" type="String" key="keys-store-password"/>
         <entry value="certs%2Ftruststore" type="String" key="trusts-store"/>
         <entry value="truststore-passwd" type="String" key="trusts-store-password"/>
         <entry value="true" type="Boolean" key="use"/>
        </map>
       </node>
      </node>
     </component>
    </tigase-config>
  2. If you want MUC component to be running inside your main server I would suggest to read this article and add it after the server is started.
  3. You need also ALL set in 2 more places:
    <entry value="ALL" type="String" key="java.util.logging.FileHandler.level"/>

    and

    <entry value="ALL" type="String" key="java.util.logging.ConsoleHandler.level"/>

Submitted by Johnny (not verified) on Sat, 2007-09-08 00:01.

Ok, now I understand more about the configuration but I still have no clue on how to config the MUC. Would you please send me a very simple config file that has the MUC configured?

Speaking of the logging. I manually changed the logging level in the tigase-config.xml file to ALL (see below) but I still don't see any of my logs from my classes:
<entry key=".level" type="String" value="ALL" />

Maybe this is not the right one?

Big Thanks!

kobit's picture
Submitted by kobit on Fri, 2007-09-07 22:56.

I am afraid you are expecting too much from the configuration wizards. Let me explain what it really is.

In short they just create XML config file using given parameters if and only if the config file is missing. If the config file exist but some settings are missing then configuration wizards add only missing parameters.

Tigase server always tries to recreate configuration file if it is missing at startup time and/or add missing configuration settings. If no parameters are given it uses default values (default configuration wizard).

By giving extra parameters to the server command you can instruct configuration generator what to put in configuration file, what components load and so on...

In your case you instructed the server to create default configuration in etc/tigase.xml file. Please have a look in this file to see what configuration settings were put there.

If you want to regenerate configuration settings with different parameters you need to delete old configuration XML file first.


Submitted by Johnny (not verified) on Fri, 2007-09-07 18:06.

I still don't know how to run the Configuration Wizards yet. I tried:
bin/tigase.sh run etc/tigase.conf
and it just ran the tigase server normaully... You have an sample tigase-config.xml that already has the MUC configured?

Here is what I have in my working tigase.conf:

ENC="-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
DRV="-Djdbc.drivers=com.mysql.jdbc.Driver"

JAVA_HOME="/usr/java/"
CLASSPATH="../libs/my_classes.jar"

JAVA_OPTIONS="${ENC} ${DRV} -server -Xms100M -Xmx100M "
TIGASE_CONFIG="etc/tigase.xml"
TIGASE_OPTIONS="--gen-config-def "

Thanks

kobit's picture
Submitted by kobit on Fri, 2007-09-07 12:47.

You are wrong ;-).

  1. By default it uses XMLRepository which work with user-repository.xml which is automatically created if it is missing. Assuming the server process has writing permissions to the filesystem. You can give different file name and full path to the XML repository in configuration and the file will be automatically created if it does not exist. (It is created only when there is something to store, i mean it won't create empty file. The file will be created after you register first user for example.)
  2. You can also use JDBCRepository and connect to "any" JDBC database. I tested it only with MySQL and PostgreSQL. In default package drivers are provided only for these 2 databases. And again, entries in database will be automatically added if they are missing, even if you use different (your own)authentication repository.
  3. The code above looks like a good start to me for the roster code.

kobit's picture
Submitted by kobit on Fri, 2007-09-07 12:39.
  1. MUC is already implemented. This is separate component for Tigase server. It is still in kind of experimental stage and there is no official release yet but it is usable and it works at muc.tigase.org. All you need to do is to go to maven.tigase.org, grab the latest snapshot of tigase-muc, place the jar file in Tigase server libs directory and restart the server. Then using your Jabber client which supports ad-hoc commands you can add and configure MUC component in your server at run-time.
  2. Configuration wizard works on both Linux and Windows. It is just easier to use it on Linux. If you look in the configuration wizards guide you can see in example conf files lines starting with TIGASE_OPTIONS. This line contains the actual options for tigase server. So you can put these options directly for your server at startup time and the configuration will be generated automatically.

Submitted by Anonymous (not verified) on Thu, 2007-09-06 22:00.

Please correct me if I'm wrong.
If I don't implement the UserRepository then Tigase doesn't work right for me because by default it uses XMLRepository class who only works with the user-repository.xml file (which I don't have).

Btw, you think the below dummy code is the right approach for implementing the Roster?
public String[] getSubnodes(String user, String node) throws UserNotFoundException, TigaseDBException
{
if (node.equalsIgnoreCase("roster")) {
String[] temp = {"aaa@localhost", "bbb@localhost", "ccc@localhost"};
return temp;
} else {
// TODO
}

return null;
}

Submitted by Johnny (not verified) on Thu, 2007-09-06 21:34.

...and how to implement MUC? Btw, I'm runing Tigase on Windows. Is there any Confirugation Wizard for Windows?

kobit's picture
Submitted by kobit on Thu, 2007-09-06 21:26.

You don't necessarily have to implement UserRepository if you implement own AuthRepository. These 2 things are separate. You can authenticate agains one data source and keep all user data in another data source.

I think the better code reference would be JDBCRepository implementation as it is much simpler then XMLRepository.

Anyway. Most of these methods have JavaDoc comments so I am not going to copy them here. Instead, I can give you general idea how the repository is designed and then purpose of all those methods should be more clear.

Repository was designed to allow keep different data without changing data structure. So there is no such thing like "user roster", "password", "vcard" in the repository design. So in future you can easily add new plugins which can keep different data without any modification to data storage backend.

How is it done?

It is kind of tree structure (XML sounds familiar?) with multiple root nodes. So it actually is more like file system. Nodes are like directories, (key:value) pairs are like files.

Root node is the kind of ID. In most cases this is user id (jid without resource part).

Thus method getUsers() which in fact returns list of all root nodes. This method, however is not normally used by the server. It is used only during data migration from one user repository to another. Therefore implementation of this method is optional. (I hope)

All methods with User in name in fact operate on top nodes.

getData() method returns single data entry for given top node (user id) and given subnodes, data key with optional default value if there is no value for given key.
For example, top node can be: "kobit@tigase.org", subnode can be: "roster" (or "roster/artur@tigase.org") just like directories, key can be "nickname".

All methods with Data in name in fact operate on the (key:value) pair - allow you to insert, delete, return the value.

Some nodes may contain many (key:value) pairs thus the method getKeys() which allows you to return a list with all keys in given node. And very similar getSubnodes which return all subnodes in given node.

The repository offer another interesting feature. You can assign more than single value to single key. So in fact the real structure is (key:value1,value2,....,valueN). As an example of such use would be hostnames key. You can assign many hostnames to this key.

And here we have all the methods with List in name. You can retrieve all values for given key, set values for given key or add new values to existing key with old values.

I hope that explains your concerns. If something is still not really clear, please let me know.


Submitted by Johnny (not verified) on Thu, 2007-09-06 20:34.

Questions about UserRepository interface.
Since we have a custom class for User Auth which implements UserAuthRepository. I guess I need to have a class to implement UserRepository as well?

I look into the UserRepository interface and the XMLRepository sample implementation and they seemed too much for me :) Would you please send me some explanations and purposes for each of the function in the interface such as:
getUsers()
addDataList()
getData()
getDataList()
getKeys()
...

Much appreciate!

kobit's picture
Submitted by kobit on Thu, 2007-09-06 07:28.
  1. Yes, this is tigase-config.xml file. There is a SessionManager section "plugins" which contains a list of all plugins which are loaded at startup time. I guess in your case you have to replace existing plugin: "jabber:iq:roster" with your implementation. The easiest way to set this configuration is at runtime using ad-hoc commands. This is described in this article.
  2. Sure, no problem I am here to help.
  3. Thank you.

Submitted by Johnny (not verified) on Thu, 2007-09-06 01:01.

1. How to plug my Roster class into Tigase? In the tigase-config.xml?
2. It's great to know that you already have something for this. We'll definitely ask you more when we get to this point.
3. Awesome!

Submitted by Johnny (not verified) on Wed, 2007-09-05 23:52.

I think I'm using latest one, tigase-server-2.9.5-b606.

--Johnny

kobit's picture
Submitted by kobit on Wed, 2007-09-05 22:53.
  1. Sample code for buddy list is in the roster plugin: JabberIqRoster.java
  2. You mean deployment of the server on multiple machines? If so, the answer is yes. The configuration, however is not so simple. It depends how many nodes you want to deploy, which components must be placed on which nodes and so on. In the simplest case where you want just to split the client connections on multiple machines and have a single node with SessionManager you can use again configuration wizards. Well, configuration wizards can be also used for much more complex cases but some features are not documented yet. Especially you should read about: --gen-config-sm and --gen-config-cs parameter. Alternatively you can describe me your needs and I can help you with configuration generation.
  3. Well, there is no limitation in software on the number of concurrent connections. The limitation is actually in operating system (number of TCP/IP sockets, number of open files and so on). Each public release is tested with 1000 opened connections and results are available on test page. And occasionally I run tests with 10k open connections and server also runs fine. Unfortunately due to my resources limitation I am unable to test the server more extensively.

kobit's picture
Submitted by kobit on Wed, 2007-09-05 22:33.

What version of the software do you use?
There used to be a problem like this in the past but I think I have fixed this already.

Is it possible for you to use current source distribution in your development environment? It would be much easier for me to diagnose the problem and help as I can easily replicate the problem or track it on my live system.

If not please tell me exact version (build number) of your installed Tigase server. I will look in sources then...


Submitted by Johnny (not verified) on Wed, 2007-09-05 22:18.

...and when an user (tester) logged in I got this WARNING:

2007-09-05 15:13:49 PacketFilter.process() WARNING: No 'to' addre
ss, can't deliver packet: <iq from="tester@localhost/Home" id="purplee1bc10b0
" type="get"><query xmlns="vcard-temp"/></iq>

Any idea?

--Johnny

Submitted by Johnny (not verified) on Wed, 2007-09-05 20:03.

Kobit,

Again, thanks for your advise. It works! And now I have some more stupid questions:

1. You have any sample code for implementing the Buddy List? We have our own database for the Buddy List already.
2. Tigase supports multi-node? If yes, how to set it up?
3. How many concurrent connections can a Tigase server handle?

Regards,
--Johnny

kobit's picture
Submitted by kobit on Sat, 2007-09-01 14:28.

I am not 100% sure because I don't know which exact version (build) of the server you use but it seems to me your implementation doesn't return valid result for the queryAuth method call.

The code puts a Map as a parameter to the method and expect result in the same Map under special key: UserAuthRepository.RESULT_KEY.

Please have a look at DrupalAuth implementation, especially this method implementation for hints how it should work.


Submitted by Johnny (not verified) on Sat, 2007-09-01 01:05.

Cool! I've made my own Auth class to implement UserAuthRepository. It initialized fine. I could see some output from the class's constructor however it threw out some exceptions when a client attempted to connect. Please see below and advice what I should do. Thanks

2007-08-31 17:59:02 AbstractMessageReceiver$QueueListener.run() SEVERE: Except
ion during packet processing:
java.lang.NullPointerException at
tigase.xmpp.impl.SaslAuth.supStreamFeatures(SaslAuth.java:108)
at
tigase.server.xmppsession.SessionManager.getFeatures(SessionManager.j
ava:508) at
tigase.server.xmppsession.SessionManager.processCommand(SessionManage
r.java:434) at
tigase.server.xmppsession.SessionManager.processPacket(SessionManager
.java:139) at
tigase.server.AbstractMessageReceiver$QueueListener.run(AbstractMessa
geReceiver.java:391) at java.lang.Thread.run(Unknown Source)

kobit's picture
Submitted by kobit on Fri, 2007-08-31 21:26.

Indeed, you are right there is no such information how to make Tigase use your custom authentication class.

Authentication class can be set for each SessionManager you load. (You can load as many session managers as you need.)

If you look in your XML configuration file you can find 2 options under session manager section:
auth-repo-class and auth-repo-url. The first sets the class to load for authentication and the second sets initialization string.

So to set these parameters you could manually edit the file and enter values you need. This is not recommended though as value string must be uuencoded. This is especially important for initialization string which may contain special characters.

The best way is to use configuration wizards. Good example how to use configuration wizards for this purpose is a guide about integration Tigase with Libre Source where such special authentication module is implemented and used.

More detailed information about configuration wizards can be found in Configuration wizards guide.

Let me know if you have any problems or you need more information.


Submitted by Johnny (not verified) on Fri, 2007-08-31 18:53.

Hi Kobit,

We're glad you're back. Good vacation?
Your response did not answer our question yet. Assuming I already have a class, MyAuth, who implements tigase.db.UserAuthRepository. How to stick this class into Tigase? Another way to say is how to force Tigase to run MyAuth class?

Is there any documentation or instruction for these kinds of things?

Thanks,
--Johnny

kobit's picture
Submitted by kobit on Fri, 2007-08-31 10:45.

You have to implement tigase.db.UserAuthRepository interface.

Sorry for late response. I was away on holiday and without access to the network... Very interesting experience ;-)

Anyway. As I mentioned to the first sentence you need to implement just this one interface. I would suggest to look at the existing implementations as a sample code:
The simplest implementation is probably: tigase.db.UserAuthRepositoryImpl. I think however much more useful as a reference code are examples in package: tigase.db.jdbc: DrupalAuth and LibreSourceAuth.

Please have a look and let me know if there is something not clear or you need more explanation. If you authentication plugin would be more useful for other installation I can also offer my help with implementing it.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.