Not logged in. · Lost password · Register
Forum: MatriX RSS
Avatar
apaulus #1
Member since Aug 2017 · 12 posts
Group memberships: Members
Show profile · Link to this post
Subject: Matrix.vnext User registration
Hi,

we are missing the XmppClient.RegisterNewAccount property in Matrix.vnext. We want our C# server to register the accounts for our users so we need this feature.

Another question related to connecting to the XMPP server: in Matrix.vnext there is no XmppClient.Hostname - instead the XmppClient.XmppDomain is used as chat server host to connect to. We really need to be able to specify the chat server host name which differs from the chat domain in our setup.

Thank you for your fast support :)
Avatar
Alex #2
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Quote by apaulus:
we are missing the XmppClient.RegisterNewAccount property in Matrix.vnext. We want our C# server to register the accounts for our users so we need this feature.

registration is not available yet. Its on our backlog and will come soon.

Quote by apaulus:
Another question related to connecting to the XMPP server: in Matrix.vnext there is no XmppClient.Hostname - instead the XmppClient.XmppDomain is used as chat server host to connect to. We really need to be able to specify the chat server host name which differs from the chat domain in our setup.

This can be done ove rthe HostnameResolver implementation.
Here is an example:

  1. xmppClient.HostnameResolver = new StaticNameResolver(IPAddress.Parse("127.0.0.1")),
Avatar
Alex #3
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
we have merged user registration today to our develop branch. I have attached a NuGet from our internal build server.

Here is a code snippet on how to use it:

  1. public class RegisterAccountHandler : IRegister
  2. {
  3.     private XmppClient xmppClient;
  4.     public RegisterAccountHandler(XmppClient xmppClient)
  5.     {
  6.         this.xmppClient = xmppClient;
  7.     }
  8.  
  9.     public bool RegisterNewAccount => true;
  10.  
  11.     public async Task<Register> RegisterAsync(Register register)
  12.     {
  13.         return await Task<Register>.Factory.StartNew(() =>
  14.         {
  15.             register.RemoveAll<Data>();
  16.             register.Username = xmppClient.Username;
  17.             register.Password = xmppClient.Password;
  18.  
  19.             return register;
  20.         });
  21.     }
  22. }
  23.  
  24.  
  25. var xmppClient = new XmppClient()
  26. {
  27.     Username = "alex",
  28.     Password = "secret",
  29.     XmppDomain = "localhost",   
  30.     HostnameResolver = new StaticNameResolver(IPAddress.Parse("127.0.0.1"), 5222)
  31. };
  32.  
  33. xmppClient.RegistrationHandler = new RegisterAccountHandler(xmppClient);
  34. await xmppClient.ConnectAsync();

Feedback is welcome before we merge this to master for an official release.

Alex
The author has attached one file to this post:
matrix.vnext.0.3.9-ci-17227-2.nupkg 437.5 kBytes
You have no permission to open this file.
Avatar
apaulus #4
Member since Aug 2017 · 12 posts
Group memberships: Members
Show profile · Link to this post
Thanks for your quick help, I'll be able to try it on Monday and will give feedback then :)
Avatar
apaulus #5
Member since Aug 2017 · 12 posts
Group memberships: Members
Show profile · Link to this post
Sorry for the delay, I finally wanted to try it out but I could not set it up unfortunately:

I tried installing the nuget package like this:

Install-Package Matrix.vnext -Source C:\Users\apaulus\Downloads -IncludePrerelease

However the assembly could not be loaded:

Warning    NU1603    Project depends on Matrix.vNext (>= 0.3.9-ci-17227-2) but Matrix.vNext 0.3.9-ci-17227-2 was not found. An approximate best match of Matrix.vNext 0.3.9 was resolved.

I even deleted the C:\Users\apaulus\.nuget\packages\Matrix.vnext folder before that but the old package must have been in another cache..

Maybe this is related to the migration of my project from

  1. <TargetFramework>netcoreapp1.1</TargetFramework>

to

  1. <TargetFramework>netcoreapp2.0</TargetFramework>

I guess I have to wait for the official release of Matrix.vnext - installing from nuget.org will most likely work.
This post was edited on 2017-09-05, 13:04 by Alex.
Avatar
Alex #6
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
release 0.4.0 is available now.

Alex
Avatar
apaulus #7
Member since Aug 2017 · 12 posts
Group memberships: Members
Show profile · Link to this post
Thank you, I was now able to try it.

- Registration works fine, after the call to
await client.ConnectAsync();
the user is registered and authenticated.

- If the user was already registered an exception is thrown, so I may need to catch this exception, then set the client.RegistrationHandler to null and finally call ConnectAsync() again to perform a regular login.
I know there is a XMPP limitation which prevents us from checking if a user account already exists so this seems to be the best way to achieve a combined login / registration.

Thanks again for the fast support  :-)
Avatar
Alex #8
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
It should throw an exception in this case.

Can you add an Xml log of a failing registration because the account was taken?
Then we can wrap this in an end to end test and make sure you get the proper exception.

Alex
Avatar
apaulus #9
Member since Aug 2017 · 12 posts
Group memberships: Members
Show profile · Link to this post
This is the stanza which causes the Matrix.RegisterException:

  1. <iq id="iFk4yBLD40+oviP32LOwgw" type="error" from="localhost" xmlns="jabber:client">
  2.  <error type="cancel">
  3.     <conflict xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
  4.     <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">The requested username already exists.</text>
  5.  </error>
  6. </iq>

This is all fine, throwing an exception here makes perfect sense, no need to change anything.
The only thing we could improve is the error handling for this exact case. Currently I do the following:

  1. catch (RegisterException e)
  2.             {
  3.                 if (e.Stanza.ToString().Contains("The requested username already exists."))
  4.                 {
  5.                     return RetryWithoutRegistrationHandler();
  6.                 }
  7.  
  8.                 throw;
  9.             }
This works with in my test environment but the string check there feels fishy ;)

Thanks again for the fast support, keep it up  :-)

PS: This is not a big issue for us, just something you could improve in the future.
This post was edited on 2017-09-05, 12:44 by Alex.
Avatar
Alex #10
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
you should not parse the string.

MatriX gives you the complete error stanza as Iq object. So look at the nested error object and base your logic on the error condition which should be ErrorCondition.Conflict for your xml example.
The text is just a human readable description which can change, while error codes and error xml tags are defined within the protocol specs.

The text varies depending on the server implementation, or may even change with a server software update.
This post was edited on 2017-09-05, 14:17 by Alex.
Avatar
apaulus #11
Member since Aug 2017 · 12 posts
Group memberships: Members
Show profile · Link to this post
Thanks for pointing me in the right direction. I knew checking for the ErrorCondition.Conflict would have been better but I could not find it at first. Now I see that I need to cast the RegisterException.Stanza to an Iq first to access the Error property.

  1. catch (RegisterException e)
  2. {
  3.     var iq = e.Stanza as Iq;
  4.     if (iq != null && iq.Error.Condition == ErrorCondition.Conflict)
  5.     {
  6.         // retry login without registering
  7.     }
  8. }
Avatar
Alex #12
Member since Feb 2003 · 4327 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
another small hint.

There is a Cast member in XmppXElement. So you could simplify your code to:

  1. if ( e.Stanza.Cast<Iq>().Error.Condition == ErrorCondition.Conflict)
  2. {
  3.    // do something here
  4. }
Avatar
apaulus #13
Member since Aug 2017 · 12 posts
Group memberships: Members
Show profile · Link to this post
nice, thanks ;)
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Forum: MatriX RSS