Reputation: 1
I recently set up a XMPP server with ejabberd. I followed this tutorial to do so:
DenshiVideo: How to setup an XMPP server (ejabberd)
I've got access to the admin interface in the browser where I can register new users and delete them. The url is like this (replace "myserver"):
http://myserver.com:5280/admin/server/myserver.com/users/
What I want to do now is be able to register new users from outside the admin interface in the browser, maybe with a Python script. I'm trying to do so using the XMPPpy library.
This is the script I tried:
`#!/usr/bin/python3
import xmpp
server = "myserver.com"
admin_username = "[email protected]"
admin_password = "password1234"
new_username = "[email protected]"
new_password = "newuserpassword1234"
def register_user(server, admin_username, admin_password, new_username, new_password):
admin_jid = xmpp.protocol.JID(admin_username)
client = xmpp.Client(server=server, debug=[])
client.connect()
# Authenticate as administrator
client.auth(user=admin_jid.getNode(), password=admin_password)
# Register a new account
iq = xmpp.Iq(to=server, typ='set')
iq.addChild("query", namespace="jabber:iq:register")
iq.getTag("query").addChild("username", payload=[new_username])
iq.getTag("query").addChild("password", payload=[new_password])
result = client.SendAndWaitForResponse(iq)
if result and result.getType() == 'result':
print("User registration successful.")
else:
print(result)
print("User registration failed.")
client.disconnect()
if __name__ == '__main__':
register_user(server, admin_username, admin_password, new_username, new_password)`
However, the ejabberd server gives me back the following error:
`<iq xmlns="jabber:client" xml:lang="en" to="[email protected]/18317692873934713179914" from="bryanyep.com" type="error" id="3">
<query xmlns="jabber:iq:register">
<username>dinaboluarte</username>
<password>ROLEX</password>
</query>
<error type="auth">
<forbidden xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
<text xml:lang="en" xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">
Access denied by service policy
</text>
</error>
</iq>
User registration failed.`
I asked ChatGPT about it and it told to do some changes in the /opt/ejabberd/conf/ejabberd.yml file, but I double-checked the file and the changes where already there. This is the 'access_rules' section on this file:
`access_rules:
local:
allow: local
c2s:
deny: blocked
allow: all
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: local
pubsub_createnode:
allow: local
trusted_network:
allow: loopback
register:
allow: all`
I'm not sure if I need to set up an API first and do a POST request, or if the API is already there and I don't know how to access it. However, there is an 'api_permissions' section on that same file:
`api_permissions:
"console commands":
from:
- ejabberd_ctl
who: all
what: "*"
"admin access":
who:
access:
allow:
- acl: loopback
- acl: admin
oauth:
scope: "ejabberd:admin"
access:
allow:
- acl: loopback
- acl: admin
what:
- "*"
- "!stop"
- "!start"
"public commands":
who:
ip: 127.0.0.1/8
what:
- status
- connected_users_number`
And just in case, this is the 'listen' section on that same file:
`listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
starttls_required: true
-
port: 5223
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
tls: true
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
shaper: s2s_shaper
-
port: 5443
ip: "::"
module: ejabberd_http
tls: true
request_handlers:
/admin: ejabberd_web_admin
/api: mod_http_api
/bosh: mod_bosh
/captcha: ejabberd_captcha
/upload: mod_http_upload
/ws: ejabberd_http_ws
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
/admin: ejabberd_web_admin
/.well-known/acme-challenge: ejabberd_acme
-
port: 3478
ip: "::"
transport: udp
module: ejabberd_stun
use_turn: true
## The server's public IPv4 address:
# turn_ipv4_address: "203.0.113.3"
## The server's public IPv6 address:
# turn_ipv6_address: "2001:db8::3"
-
port: 1883
ip: "::"
module: mod_mqtt
backlog: 1000`
Please, if anyone knows how to do this I'll be very thankful. And sorry for the n00b question, this is my first time working with the XMPP protocol.
Thank you all in advance.
Upvotes: 0
Views: 211
Reputation: 4120
There are two ways to register programmatically an account in ejabberd:
A) Using the XMPP method: First configure mod_register to allow any XMPP clients to register accounts. Or you could allow registration only from IP address 127.0.0.1. Then write a small Python script that behaves like a regular XMPP client: it connects to port 5222 and registers an account like any other client.
B) Using ejabberd's register
API command: First configure a listener with ejabberd_http and mod_http_api, also grant access with option api_permissions. Then write a small Python script that sends an HTTP query to port 5443 and will be handled by mod_http_api.
Looking at your question, you are mixing stuff: your python script and access_rules are useful for method A. On the other hand, api_permissions is useful only for method B. Finally, the listen configuration is valid for method A and for method B.
I'll provide an example to use method B. I'll assume you start with the default configuration, that way when other person finds this thread, they can follow the example without needing to understand your previous configuration.
listen
section must include a port with module ejabberd_http and mod_http_api, for example:listen:
-
port: 5443
module: ejabberd_http
tls: true
request_handlers:
/api: mod_http_api
api_permissions
must allow your desired connection, but disallow the rest. For example, this works in my case:api_permissions:
"console commands":
from:
- ejabberd_ctl
who: all
what: "*"
"admin access":
from:
- mod_http_api
who:
access:
allow:
- acl: loopback
- acl: admin
what:
- register
modules
section must include the module. Probably you already have it enabled, but just to make sure, check:modules:
...
mod_http_api: {}
acl:
admin: [user: tim]
loopback:
ip:
- 127.0.0.0/8
- ::1/128
$ ejabberdctl register tim localhost somepass
User tim@localhost successfully registered
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
import requests
from requests.auth import HTTPBasicAuth
url = "https://localhost:5443/api/register"
data = {
"user": "username2",
"host": "localhost",
"password": "somepassword"
}
res = requests.post(url, json=data, auth=HTTPBasicAuth("tim@localhost", "somepass"), verify=False)
print(res)
$ python3 register.py
<Response [200]>
$ ejabberdctl registered_users localhost
tim
username2
$ ejabberdctl check_password username2 localhost somepassword
$ echo $?
0
Upvotes: 0