processone / ejabberd

Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
https://www.process-one.net/en/ejabberd/
Other
6k stars 1.5k forks source link

Why is external plugin verification one-time? #4149

Closed happy-berry closed 5 months ago

happy-berry commented 5 months ago

My externale plugin already passed verify, but when the password changes, logging in again can be done through the plugin, but it will not be done through ejabberd. Why is this?

licaon-kter commented 5 months ago

What is an external plugin?

Which ejabberd version? Which OTP version? OS? How did you install ejabberd?

Link to your plugin?

Do add more details...

happy-berry commented 5 months ago

ejabberd version : new os : ubantu(amd 64) Is a golang external program . my config:

```yml hosts: - 101.43.219.42 auth_method: - external extauth_program: "/xmpp/service-chat" extauth_cache: 0 extauth_instances: 10 loglevel: info ca_file: /opt/ejabberd/conf/cacert.pem certfiles: - /opt/ejabberd/conf/server.pem ## If you already have certificates, list them here # certfiles: # - /etc/letsencrypt/live/domain.tld/fullchain.pem # - /etc/letsencrypt/live/domain.tld/privkey.pem 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 /api: mod_http_api /.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 s2s_use_starttls: optional acl: admin: user: sans@101.43.219.42 local: user_regexp: "" loopback: ip: - 127.0.0.0/8 - ::1/128 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 api_permissions: "API used from localhost allows all calls": who: all what: - "*" - "!stop" - "!start" shaper: normal: rate: 3000 burst_size: 20000 fast: 100000 shaper_rules: max_user_sessions: 10 max_user_offline_messages: 5000: admin 100: all c2s_shaper: none: admin normal: all s2s_shaper: fast modules: mod_adhoc: {} mod_admin_extra: {} mod_announce: access: announce mod_avatar: {} mod_blocking: {} mod_bosh: {} mod_caps: {} mod_carboncopy: {} mod_client_state: {} mod_configure: {} mod_disco: {} mod_fail2ban: {} mod_http_api: {} mod_http_upload: put_url: https://@HOST@:5443/upload custom_headers: "Access-Control-Allow-Origin": "https://@HOST@" "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS" "Access-Control-Allow-Headers": "Content-Type" mod_last: {} mod_mam: ## Mnesia is limited to 2GB, better to use an SQL backend ## For small servers SQLite is a good fit and is very easy ## to configure. Uncomment this when you have SQL configured: ## db_type: sql assume_mam_usage: true default: always mod_mqtt: {} mod_muc: access: - allow access_admin: - allow: admin access_create: muc_create access_persistent: muc_create access_mam: - allow default_room_options: mam: true mod_muc_admin: {} mod_offline: access_max_user_messages: max_user_offline_messages mod_ping: {} mod_privacy: {} mod_private: {} mod_proxy65: access: local max_connections: 5 mod_pubsub: access_createnode: pubsub_createnode plugins: - flat - pep force_node_config: ## Avoid buggy clients to make their bookmarks public storage:bookmarks: access_model: whitelist mod_push: {} mod_push_keepalive: {} mod_register: ## Only accept registration requests from the "trusted" ## network (see access_rules section above). ## Think twice before enabling registration from any ## address. See the Jabber SPAM Manifesto for details: ## https://github.com/ge0rg/jabber-spam-fighting-manifesto ip_access: trusted_network mod_roster: versioning: true mod_s2s_dialback: {} mod_shared_roster: {} mod_stream_mgmt: resend_on_timeout: if_offline mod_stun_disco: {} mod_vcard: {} mod_vcard_xupdate: {} mod_version: show_os: false ```

I used the user's token as the password to complete the login process, but I found that when the user's password changed, I couldn't log in again using the plugin. There was no problem printing my plugin logs, and I had completed the plugin process completely. However, it seems that the plugin will not be used again to process my login process in ejabberd. Is my external program code :

```golang func main() { logFile, err := os.OpenFile("/xmpp/auth.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) if err != nil { panic(err) } log.SetOutput(logFile) log.Println("Start!") bioIn := bufio.NewReader(os.Stdin) bioOut := bufio.NewWriter(os.Stdout) var success bool var length uint16 var result uint16 for { _ = binary.Read(bioIn, binary.BigEndian, &length) buf := make([]byte, length) r, err := bioIn.Read(buf) if r == 0 || err != nil { time.Sleep(25 * time.Millisecond) continue } log.Println("读取到数据,处理业务流程!") if err == nil { data := strings.Split(string(buf[:r]), ":") if data[0] == "auth" { success, err = auth(data[1], data[2], data[3]) } else if data[0] == "isuser" { success, err = isuser(data[1], data[2]) } else { success = false } } else { success = false } length = 2 binary.Write(bioOut, binary.BigEndian, &length) if success != true { result = 0 } else { result = 1 } binary.Write(bioOut, binary.BigEndian, &result) bioOut.Flush() } log.Println("End!") } // user pass 对应uid token 校验 func auth(user, server, passwd string) (bool, error) { log.Printf("auth: %s, server: %s, passwd: %s \n", user, server, passwd) if err := post(httpParam{ Url: "https://beta.xyplay.cn/service_user/api/v2/uuid/uid/tokenVerify", Body: map[string]string{"uid": user}, Auth: "Bearer " + passwd, TimeOut: 5, Header: nil, Callback: func(b []byte) error { rspBody := struct { Code int `json:"code"` Mess string `json:"msg"` }{} json.Unmarshal(b, &rspBody) if rspBody.Code != 0 { return errors.New(rspBody.Mess) } return nil }, }); err != nil { return false, err } return true, nil } ```
licaon-kter commented 5 months ago

ejabberd version : new

Is that 20.01-new or 23.10-new or self compiled ejabberd from HEAD, or from ejabberd.im .run installer or .deb

os : ubantu(amd 64),

which one? 20.04 LTS or 23.10? Maybe in between

happy-berry commented 5 months ago

23.10

happy-berry commented 5 months ago

my ubantu version : 20.04

badlop commented 5 months ago

when the user's password changed, I couldn't log in again using the plugin

It seems ejabberd has stored in its cache the password used in the first login. You try to disable caching with this option:

extauth_cache: 0

Do you get a warning message like this one?

2024-01-18 16:56:48.507762+01:00 [warning] Option 'extauth_cache' is deprecated and has no effect, use authentication or global cache configuration options: auth_use_cache, auth_cache_life_time, use_cache, cache_life_time, and so on

The option you are using to disable caching does not exist anymore. And caching is enabled by default.

Please use auth_use_cache, as explained in the External Script documentation:

auth_use_cache: false
happy-berry commented 5 months ago

ah..... which API should I call to remove users from the chat room ? I have already tried muc_unregister_nick、kick_user。

badlop commented 5 months ago

which API should I call to remove users from the chat room ?

It depends on what you mean by "remove user". How did you add the users?

happy-berry commented 5 months ago

I use send_direct_invitation

happy-berry commented 5 months ago

I want I want to invite all users to one room and remove, is my step 1、 create_room 2、send_direct_invitation 3、muc_unregister_nick/kick_user 4、 destroy_room but I found it can't remove user

happy-berry commented 5 months ago

But there is only one API that can remove users from chat rooms(kick_user), but it will disconnect the user's session, may I ask what I should do?