Plugin development for authentication

46 posts / 0 new
Last post
Anonymous
Plugin development for authentication

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

Application: 

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.

Johnny

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

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.

Johnny

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)

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.

Johnny

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

Johnny

...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

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...

  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.
Johnny

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

--Johnny

Johnny

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!

  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.
Johnny

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!

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.

Johnny

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

Anonymous

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;
}

  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.

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.
Johnny

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

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.

Johnny

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!

  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"/>
Johnny

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 ;)

  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.
Johnny

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

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>
Johnny

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

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.

Johnny

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

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
Anonymous

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?

> 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!

Hap

So I have created a custom auth class that extends tigase.db.UserAuthRepositoryImpl class (which in turn implements UserAuthRepository interface).

I am trying to determine how to get this custom auth class to deploy to Tigase server.

I have read all of the following links but it is still not clear to me how to do this correctly.
tigase-server-custom-authentication-using-web-services
tigase-custom-authenticating-against-external-database-custom-sql-queries
tigase-auth-connector
tigase-custom-auth-connector
custom-authentication-connectors
Integrating Tigase server with LibreSource

I am running Tigase Server 5.0.0-b2135. After installing this server, I do not see a etc/tigase.xml prior to starting the server nor after starting the server. I start the server like this from {tigase_home::

./scripts/tigase.sh start etc/tigase.conf

I am using the standard tigase.sh file that came with 5.0.0-b2135 server.

Here is my etc/tigase.sh file:

ENC="-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
DRV="-Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver:org.apache.derby.jdbc.EmbeddedDriver"
#GC="-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:ParallelCMSThreads=2"
JAVA_HOME="/usr/java/latest"
CLASSPATH=""
JAVA_OPTIONS="${GC} ${ENC} ${DRV} -server -Xms100M -Xmx200M -XX:PermSize=32m -XX:MaxPermSize=256m -XX:MaxDirectMemorySize=128m "
TIGASE_CONFIG="etc/tigase.xml"
TIGASE_OPTIONS=" --property-file etc/init.properties "

Here is my etc/init.properties file:

--user-db = mysql
--admins = admin@dev-tigase-xmpp
--user-db-uri = jdbc:mysql://localhost/tigasedb?user=tigase&password=passwd
config-type = --gen-config-def
--virt-hosts = dev-tigase-xmpp
--debug = server,tigase.xmpp.impl,db,xmpp.XMPIOService,tigase.io,tigase.net,tigase.xml,tigase.server.bosh
--comp-name-1=pubsub
--comp-class-1=tigase.pubsub.PubSubComponent
--comp-name-2=drm-tigase-auth
--comp-class-2=com.CustomAuth
--monitoring=jmx:9050,http:9080,snmp:9060
bosh/max-inactivity[L]=60

After reading the other posts, it seems like I need to set something in my init.properties file but if that is true, it's not clear what to set.

Hi Greg,

You, indeed, missed one bit in the configuration file. Custom authentication connector is not configured using --comp-class/name property.
To load your own authentication connector you have to set --auth-db property. In your case the configuration would look like this:

--auth-db=com.CustomAuth

Of course you may need to set DB connection string in a property: --auth-db-uri if it is different from the main user repository database.

I hope this helps, if not, please let me know.

Hap

Thank you for the clarification. I did set that property value so my init.properties now looks like this:

--user-db = mysql
--admins = admin@localhost
--user-db-uri = jdbc:mysql://localhost/tigasedb?user=tigase&password=passwd
config-type = --gen-config-def
--virt-hosts = localhost
--comp-name-1=pubsub
--comp-class-1=tigase.pubsub.PubSubComponent
--auth-db=com.CustomAuth
--monitoring=jmx:9050,http:9080,snmp:9060
--debug = server,tigase.xmpp.impl,db,xmpp.XMPIOService,tigase.io,tigase.net,tigase.xml,tigase.server.bosh

Unfortunately, I am getting an error in the tigase-console log trying to instantiate the class. Here is the log output:

STARTED Tigase Tue Apr 26 12:51:32 MDT 2011
2011-04-26 12:51:32 DNSResolver.() WARNING: Resolving default host name took: 8
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Setting defaults: -c=etc/tigase.xml
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Setting defaults: --property-file=etc/init.properties
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Loading initial properties from property file: etc/init.properties
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (config-type=--gen-config-def)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--monitoring=jmx:9050,http:9080,snmp:9060)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--debug=server,tigase.xmpp.impl,db,xmpp.XMPIOService,tigase.io,tigase.net,tigase.xml,tigase.server.bosh)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--user-db=mysql)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--auth-db=com.CustomAuth)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--admins=admin@localhost)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--user-db-uri=jdbc:mysql://localhost/tigasedb?user=tigase&password=passwd)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--virt-hosts=localhost)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--comp-class-1=tigase.pubsub.PubSubComponent)
2011-04-26 12:51:32 ConfiguratorAbstract.parseArgs() CONFIG: Added default config parameter: (--comp-name-1=pubsub)
2011-04-26 12:51:32 MonitoringSetup.initMonitoring() CONFIG: Installing monitoring services: jmx:9050,http:9080,snmp:9060
2011-04-26 12:51:32 MonitoringSetup.initMonitoring() CONFIG: Loading JMX monitor.
2011-04-26 12:51:32 MonitoringSetup.initMonitoring() CONFIG: Loading HTTP monitor.
2011-04-26 12:51:32 MonitoringSetup.initMonitoring() CONFIG: Loading SNMP monitor.
2011-04-26 12:51:33 MessageRouter.addRegistrator() INFO: Adding registrator: Configurator
2011-04-26 12:51:33 MessageRouter.addComponent() INFO: Adding component: Configurator
2011-04-26 12:51:33 ConfiguratorAbstract.componentAdded() CONFIG: component: basic-conf
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: sess-man
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: vhost-man,ext
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: vhost-man,ext
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: vhost-man,ext
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: vhost-man,ext
2011-04-26 12:51:33 Script.init() INFO: Initialized script command, lang: groovy, ext: groovy
2011-04-26 12:51:33 BasicComponent.loadScripts() CONFIG: basic-conf: Loaded admin command from file: scripts/admin/ConfigList.groovy, id: config-list, ext: groovy, descr: List server/component configuration
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: sess-man
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: sess-man
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: sess-man
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: sess-man
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: sess-man
2011-04-26 12:51:33 BasicComponent.loadScripts() INFO: Admin script for a different component: sess-man
2011-04-26 12:51:33 ConfiguratorAbstract.setProperties() SEVERE: Can't initialize auth repository: java.lang.InstantiationException: com.CustomAuth
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at tigase.db.RepositoryFactory.getAuthRepository(RepositoryFactory.java)
at tigase.conf.ConfiguratorAbstract.setProperties(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.setup(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.server.AbstractComponentRegistrator.addComponent(AbstractComponentRegistrator.java)
at tigase.server.MessageRouter.addRegistrator(MessageRouter.java)
at tigase.server.MessageRouter.setConfig(MessageRouter.java)
at tigase.server.XMPPServer.main(XMPPServer.java)

2011-04-26 12:51:33 ConfiguratorAbstract.setProperties() SEVERE: Can't initialize auth repository: java.lang.InstantiationException: com.CustomAuth
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at tigase.db.RepositoryFactory.getAuthRepository(RepositoryFactory.java)
at tigase.conf.ConfiguratorAbstract.setProperties(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.setup(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.server.AbstractComponentRegistrator.addComponent(AbstractComponentRegistrator.java)
at tigase.server.MessageRouter.addRegistrator(MessageRouter.java)
at tigase.server.MessageRouter.setConfig(MessageRouter.java)
at tigase.server.MessageRouter.setProperties(MessageRouter.java)
at tigase.conf.ConfiguratorAbstract.setup(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.server.AbstractComponentRegistrator.addComponent(AbstractComponentRegistrator.java)
at tigase.server.MessageRouter.addRegistrator(MessageRouter.java)
at tigase.server.MessageRouter.setConfig(MessageRouter.java)
at tigase.server.XMPPServer.main(XMPPServer.java)
2011-04-26 12:51:34 SocketReadThread.getInstance() WARNING: 4 SocketReadThreads started.
2011-04-26 12:51:34 SessionManager.setProperties() SEVERE: Can't initialize auth repository: java.lang.InstantiationException: com.CustomAuth
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at tigase.db.RepositoryFactory.getAuthRepository(RepositoryFactory.java)
at tigase.server.xmppsession.SessionManager.setProperties(SessionManager.java)
at tigase.conf.ConfiguratorAbstract.setup(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.server.AbstractComponentRegistrator.addComponent(AbstractComponentRegistrator.java)
at tigase.server.MessageRouter.addComponent(MessageRouter.java)
at tigase.server.MessageRouter.addRouter(MessageRouter.java)
at tigase.server.MessageRouter.setProperties(MessageRouter.java)
at tigase.conf.ConfiguratorAbstract.setup(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.conf.ConfiguratorAbstract.componentAdded(ConfiguratorAbstract.java)
at tigase.server.AbstractComponentRegistrator.addComponent(AbstractComponentRegistrator.java)
at tigase.server.MessageRouter.addRegistrator(MessageRouter.java)
at tigase.server.MessageRouter.setConfig(MessageRouter.java)
at tigase.server.XMPPServer.main(XMPPServer.java)

Loading plugin: jabber:iq:auth=4 ...
Loading plugin: urn:ietf:params:xml:ns:xmpp-sasl=4 ...
Loading plugin: urn:ietf:params:xml:ns:xmpp-bind=2 ...
Loading plugin: urn:ietf:params:xml:ns:xmpp-session=2 ...
Loading plugin: roster-presence=8 ...
Loading plugin: jabber:iq:privacy=2 ...
Loading plugin: msgoffline=4 ...
Loading plugin: jabber:iq:version=2 ...
Loading plugin: http://jabber.org/protocol/stats=2 ...
Loading plugin: starttls=2 ...
Loading plugin: vcard-temp=2 ...
Loading plugin: http://jabber.org/protocol/commands=2 ...
Loading plugin: jabber:iq:private=2 ...
Loading plugin: urn:xmpp:ping=2 ...
Loading plugin: domain-filter=0 ...
Loading plugin: disco=2 ...

That error is a little vague into what the issue is unfortunately. Do you have any suggestions as to how I can try down the issue?

Apparently the server cannot create instance of the authentication connector class provided. Please make sure it is in the classpath, or the jar file with the class is in the libs/ directory. Also make sure the class implement correct interface: tigase.db.AuthRepository. The API for the interface changed slightly between version 5.0 and 5.1 therefore make sure you use the correct sources version when working on the code.

Hap

I understand that the error is saying it couldn't create an instance, the error just doesn't say why so it's hard to debug.

The jar is in the jars/ directory so no issue there.

com.CustomAuth is extending tigase.db.UserAuthRepositoryImpl which in turn implements tigase.db.AuthRepository so no issue there.

Because my class is extending the UserAuthRepositoryImpl that comes from the Tigase server I am running, there isn't an issue either with the version of UserAuthRepositoryImpl that I am extending.

So, given all that, what else can I do to determine why this class is not getting created?

Seems like I have followed what I need to.

As I said your library must be in libs/ directory not in jars/. Otherwise, if this is not what cause the problem, the only suggestion I have is to use SVN version instead of the 5.0.0 and build your library from this API. It would be much easier to debug and find the real source of the problem.

Hap

Sorry, I meant to say libs/ directory and not the jars/ directory.

So it sounds like my only option at this point is to build from source and debug from there.

I think this is the best option anyway. If you develop for Tigase direct access to source codes is always helpful. Moreover, the Tigase 5.1.0 version contains some API changes. Maybe not dramatic but if you code for the version right now you do not have to worry about transition when the version 5.1.0 is finally released.
On the other hand, I am really surprised with the problem you presented. It did not happen yet. It might be either API compatibility issue or maybe class instantiation... Does your class have an empty, public constructor?

Hap

So as I stated on my earlier posts, I was extending UserAuthRepositoryImpl class since that was mentioned at the beginning of this thread.

That class does not have a non-arg constructor which was the base problem. After further looking into the code, there is a very tight coupling and cyclical dependency of that class and JDBCRepository. So tight and cyclical in fact that I would say there is a "code smell" there at least in the 5.0.X source (haven't looked at 5.1.X yet).

Anyway, I was able to find another work-around to the problem and I now understand the auth piece better. I am also building and deploy server version 5.0.4 now so that's a good thing.

There is no direct reference from UserAuthRepositoryImpl to JDBCRepository so I don't think you can call it a cyclical dependency. In fact, UserAuthRepositoryImpl could be coupled with any UserRepository implementation.
On the other hand, using UserAuthRepositoryImpl as a base class for your own implementation is a bit unfortunate as this is not really a typical AuthRepository implementation.
You should rather look at TigaseAuth or TigaseCustomAuth implementation.

And once again, if you are seriously thinking of codding extensions for the Tigase I highly suggest to use at least 5.1.0-beta2 if not SVN trunk. There were some API changes and you probably don't want to port your code in a few weeks to a new version.

Hap

I beg to differ.

The tagged 5.0.4 version I checked out of SVN for the server has JDBCRespository explicitly instantiating UserAuthRepositoryImpl in it's initRepo() method and passing itself as the repo for that instantiation and because JDBCRepository also implements UserAuthRepostory interface (another code smell) it delegates some of the implemented UserAuthRepository interface methods to UserAuthRepositoryImpl. Then (and here is where the cyclical dependency really comes in), some of the UserAuthRepository interface methods that UserAuthRepositoryImpl implements actually call back to JDBCRepository - thus creating the cyclical dependency. For example:

  • getResourceUri()
  • updatePassword()
  • removeUser()
  • addUser()
  • getUserCount()
  • getUsersCount()

Now, I haven't looked at source for 5.1.x yet so maybe these issue have been addressed in that version/ We are looking at moving to 5.1.X here eventually, we just wanted to start with a non-beta version first in hopes of starting with best stability.

Let me address your points above:

  1. While this is true that the JDBCRepository is explicitly instantiating UserAuthRepositoryImpl and is passing itself to the constructor, please note that UserAuthRepositoryImpl accepts in the constructor any UserRepository implementation. There is no reference to the class JDBCRepository inside the UserAuthRepositoryImpl. So you can easily create your own UserRepository implementation, let's say LDAPRepository, which can delegate authentication logic to the UserAuthRepositoryImpl the same way JDBCRepository does. Therefore there is no cyclic dependency in the implementation classes.
  2. I also does not understand why you think that JDBCRepository implementing UserAuthRepostory is a code smell as you call it. Isn't it a proper code design to expose API through interfaces and implementing interfaces in classes?

Maybe your strong opinion about the code is a result of misunderstanding of the design?
Let me explain it to you:

In the Tigase we have two main types of repository: UserRepository where all the user's data is stored (roster, privacy lists, private data storage, vcard, etc...) and AuthRepository where user's authentication data is stored.

This is to make is easy to integrate Tigase with external systems, where user accounts are kept in let's say website database and user's XMPP data in Tigase own database.
So you can easily split authentication data from the rest of user's data.

However, in most cases and default installations, users' authentication data are really stored in the Tigase own database so in fact we keep everything in a single database.
But even then authentication data is accessed through a different API then other information.

Please also note that user authentication processing is always the same regardless what data storage you use, LDAP, Webservices, regular SQL database. SASL is SASL, non-SASL is non-SASL. You always process authentication data in the same way.

This is why UserAuthRepositoryImpl has been implemented. It just handles user's authentication data in certain way. Authentication logic is hidden there and it loads actual data from UserRepository object, whatever it is. So you can couple it with JDBCRepository, LDAPRepository, WSRepository, whatever you want. The UserAuthRepositoryImpl does not care where it loads data from.

Now, JDBCRepository is a class which loads user's data from database via JDBC driver. It implements both AuthRepository and UserRepository because in most cases there is only one data storage. So we can simplify server configuration by using just one class implementing both interfaces. To reduce the code and avoid code duplication it delegates authentication logic to UserAuthRepositoryImpl while serving all the data which is required.

I hope this explains how this all works.

Bterm

I'm running into the same issue with implementing AuthRepository as noted above, code snippet and error posted here:

http://www.tigase.org/content/custom-user-auth-plugin-severe-cant-initialize-auth-default-repository

What am I missing?