tinode / chat

Instant messaging platform. Backend in Go. Clients: Swift iOS, Java Android, JS webapp, scriptable command line; chatbots
GNU General Public License v3.0
12.03k stars 1.88k forks source link

REST Auth Problem #859

Closed pkuwwt closed 1 year ago

pkuwwt commented 1 year ago

REST Auth Problem

I use the code auth.py and the dummy_data.json as the external rest auth server. The /auth request is handled. However, there is an init_topic error.

Your environment

Server-side

Client-side

Steps to reproduce

docker-compose.yml

version: "3.0"
services:
  chat:
    image: tinode/tinode-postgres
    restart: always
    ports:
      - 6060:6060
    environment:
      - POSTGRES_DSN=postgresql://postgres:postgres@db:5432/tinode
    volumes:
      - ./config.template:/opt/tinode/config.template
  db:
    image: postgres
    restart: always
    environment:
      - POSTGRES_PASSWORD=postgres
  demo-auth-server:
    image: tinode-demo/demo-auth-server
    build:
      context: demo-auth-server
    restart: always

config.template

{
    "listen": ":6060",
    "api_path": "/",
    "cache_control": 39600,
    "static_mount": "/",
    "grpc_listen": ":16060",
    "api_key_salt": "$API_KEY_SALT",
    "max_message_size": 4194304,
    "max_subscriber_count": 32,
    "max_tag_count": 16,
    "expvar": "/stats/expvar/",
    "server_status": "$SERVER_STATUS_PATH",

    "media": {
        "use_handler": "$MEDIA_HANDLER",
        "max_size": 33554432,
        "gc_period": 60,
        "gc_block_size": 100,
        "handlers": {
            "fs": {
                "upload_dir": "uploads"
            },
            "s3":{
                "access_key_id": "$AWS_ACCESS_KEY_ID",
                "secret_access_key": "$AWS_SECRET_ACCESS_KEY",
                "region": "$AWS_REGION",
                "bucket": "$AWS_S3_BUCKET",
                "cors_origin": $AWS_CORS_ORIGINS
            }
        }
    },

    "tls": {
        "enabled": $TLS_ENABLED,
        "http_redirect": ":80",
        "strict_max_age": 604800,
        "autocert": {
            "cache": "/etc/letsencrypt/live/$TLS_DOMAIN_NAME",
            "email": "$TLS_CONTACT_ADDRESS",
            "domains": ["$TLS_DOMAIN_NAME"]
        }
    },

    "auth_config": {
        "logical_names": ["basic:rest", "rest:"],
        "rest": {
            "server_url": "http://demo-auth-server:5000/",
            "use_separate_endpoints": true
        },
        "token": {
            "expire_in": 1209600,
            "serial_num": 1,
            "key": "wfaY2RgF2S1OQI/ZlK+LSrp1KB2jwAdGAIHQ7JZn+Kc="
        }
    },

    "store_config": {
        "uid_key": "$UID_ENCRYPTION_KEY",
        "use_adapter": "$STORE_USE_ADAPTER",
        "adapters": {
            "mysql": {
                "database": "tinode",
                "dsn": "$MYSQL_DSN?parseTime=true&collation=utf8mb4_unicode_ci"
            },
            "postgres": {
                "database": "tinode",
                "dsn": "$POSTGRES_DSN?sslmode=disable"
            },
            "rethinkdb": {
                "database": "tinode",
                "addresses": "rethinkdb"
            },
            "mongodb": {
                "database": "tinode",
                "addresses": "mongodb",
                "replica_set": "rs0"
            }
        }
    },
    "acc_validation": {
        "email": {
            "add_to_tags": true,
            "required": [$EMAIL_VERIFICATION_REQUIRED],
            "config": {
                "host_url": "$SMTP_HOST_URL",
                "smtp_server": "$SMTP_SERVER",
                "smtp_port": "$SMTP_PORT",
                "login": "$SMTP_LOGIN",
                "sender": "$SMTP_SENDER",
                "sender_password": "$SMTP_PASSWORD",
                "languages": ["en", "ru"],
                "validation_templ": "./templ/email-validation-{{.Language}}.templ",
                "reset_secret_templ": "./templ/email-password-reset-{{.Language}}.templ",
                "max_retries": 4,
                "domains": [$SMTP_DOMAINS],
                "debug_response": "$DEBUG_EMAIL_VERIFICATION_CODE"
            }
        },
        "tel": {
            "add_to_tags": true,
            "config": {
                "validation_templ": "./templ/sms-validation-{{.Language}}.templ",
                "reset_secret_templ": "./templ/sms-password-reset-{{.Language}}.templ",
                "max_retries": 4,
                "debug_response": "$DEBUG_TEL_VERIFICATION_CODE"
            }
        }
    },
    "acc_gc_config": {
        "gc_period": 3600,
        "gc_block_size": 10,
        "gc_min_account_age": 48
    },
    "push": [
    {
        "name":"tnpg",
        "config": {
            "enabled": $TNPG_PUSH_ENABLED,
            "token": "$TNPG_AUTH_TOKEN",
            "org": "$TNPG_USER"
        }
    },
    {
        "name":"fcm",
        "config": {
            "enabled": $FCM_PUSH_ENABLED,
            "project_id": "$FCM_PROJECT_ID",
            "credentials_file": "$FCM_CRED_FILE",
            "time_to_live": 3600,
            "android": {
                "enabled": $FCM_INCLUDE_ANDROID_NOTIFICATION,
                "icon": "ic_logo_push",
                "icon_color": "#3949AB",
                "click_action": ".MessageActivity",
                    "msg": {
                        "title_loc_key": "new_message",
                        "title": "",
                        "body_loc_key": "",
                        "body": ""
                    },
                    "sub": {
                        "title_loc_key": "new_chat",
                        "body_loc_key": ""
                    }
                }
            }
        }
    ],

    "webrtc": {
        "enabled": $WEBRTC_ENABLED,
        "call_establishment_timeout": 30,
        "ice_servers_file": "$ICE_SERVERS_FILE"
    },

    "cluster_config": {
        "self": "",
        "nodes": [
            {"name": "tinode-0", "addr": "tinode-0:12000"},
            {"name": "tinode-1", "addr": "tinode-1:12001"},
            {"name": "tinode-2", "addr": "tinode-2:12002"}
        ],
        "num_proxy_event_goroutines": $CLUSTER_NUM_PROXY_EVENT_GOROUTINES,
        "failover": {
            "enabled": true,
            "heartbeat": 100,
            "vote_after": 8,
            "node_fail_after": 16
        }
    },

    "plugins": [
        {
            "enabled": $PLUGIN_PYTHON_CHAT_BOT_ENABLED,
            "name": "python_chat_bot",
            "timeout": 20000,
            "filters": {
                "account": "C"
            },
            "failure_code": 0,
            "failure_text": null,
            "service_addr": "tcp://localhost:40051"
        }
    ]
}

auth server

demo-auth-server/requirements.txt

flask

demo-auth-server/Dockerfile

FROM python:3.10-slim
WORKDIR /dist/
ADD requirements.txt /dist/
RUN pip install -r requirements.txt
ADD app.py /dist/
ADD dummy_data.json /dist/
ENTRYPOINT ["python3", "app.py"]

The demo-auth-server/app.py and demo-auth-server/dummy_data.json are from https://github.com/tinode/chat.

Execute by

sudo docker-compose up -d

Expected behaviour

Login with bob:bob123 at 127.0.0.1:6060.

Actual behaviour

error displayed on web

Disconnected by client (418)

Server-side log

I2023/05/01 02:37:31 ws: session started 8kcyc3z9Cg0 172.20.0.1:56570 2
I2023/05/01 02:37:31 in: '{"hi":{"id":"80009","ver":"0.22.6","ua":"TinodeWeb/0.22.6 (Chrome/112.0; MacIntel); tinodejs/0.22.6","lang":"en-US","platf":"web"}}' sid='8kcyc3z9Cg0' uid=''
I2023/05/01 02:37:31 in: '{"login":{"id":"80010","scheme":"basic","secret":"YWxpY2U6YWxpY2UxMjM="}}' sid='8kcyc3z9Cg0' uid=''
I2023/05/01 02:37:37 ws: session started oD3GadWnj9A 172.20.0.1:56576 2
I2023/05/01 02:37:37 in: '{"hi":{"id":"109362","ver":"0.22.6","ua":"TinodeWeb/0.22.6 (Chrome/112.0; MacIntel); tinodejs/0.22.6","lang":"en-US","platf":"web"}}' sid='oD3GadWnj9A' uid=''
I2023/05/01 02:37:37 in: '{"login":{"id":"109363","scheme":"basic","secret":"Ym9iOmJvYjEyMw=="}}' sid='oD3GadWnj9A' uid=''
I2023/05/01 02:37:37 in: '{"sub":{"id":"109364","topic":"me","get":{"what":"sub desc tags cred"}}}' sid='oD3GadWnj9A' uid='Pp-n0RjGm8s'
E2023/05/01 02:37:37 init_topic: failed to load or create topic: usrPp-n0RjGm8s user not found
E2023/05/01 02:37:38 ws: readLoop oD3GadWnj9A websocket: close 1005 (no status)

Client-side log

websocket message

{"hi":{"id":"80009","ver":"0.22.6","ua":"TinodeWeb/0.22.6 (Chrome/112.0; MacIntel); tinodejs/0.22.6","lang":"en-US","platf":"web"}}
{"ctrl":{"id":"80009","params":{"build":"postgres:v0.22.6","maxFileUploadSize":33554432,"maxMessageSize":4194304,"maxSubscriberCount":32,"maxTagCount":16,"maxTagLength":96,"minTagLength":2,"reqCred":null,"ver":"0.22"},"code":201,"text":"created","ts":"2023-05-01T02:37:31.952Z"}}
{"login":{"id":"80010","scheme":"basic","secret":"YWxpY2U6YWxpY2UxMjM="}}
{"ctrl":{"id":"80010","code":404,"text":"not found","ts":"2023-05-01T02:37:31.956Z"}}
or-else commented 1 year ago

Please provide correct full logs. Your client-side and server-side logs are from different sessions (9 minutes apart). Your client-side log is incomplete.

Also, it seems like you have not created the user usrQVuwC5jz9o4.

pkuwwt commented 1 year ago

@or-else I updated the log.

I don't known where the usrQVuwC5jz9o4 comes from.

or-else commented 1 year ago

I cannot give you any advice because you did not provide enough information.

or-else commented 1 year ago

also, show the logs from your restauth server.

pkuwwt commented 1 year ago

@or-else rest auth server is just the auth.py and dummy_data.json. There is no detailed logs, just sth like

[01/May/2023 21:49:26] "POST /auth HTTP/1.1" 200

All responses are from dummy_data.json.

I searched the code, and found that usrQVuwC5jz9o4 is the topic name, and QVuwC5jz9o4 is the uid of the user in dummy_data.json.

In the server code init_topic.go:initTopicMe(),

user, err := store.Users.Get(types.ParseUserId(t.name)

t.name is the usrQVuwC5jz9o4, the parsed uid is QVuwC5jz9o4, and the returned user is nil.

I guess the server get the uid by /auth from auth server, and search it it database, which obviously not work.

or-else commented 1 year ago

You are attempting to login as alice and login fails:

{"login":{"id":"80010","scheme":"basic","secret":"YWxpY2U6YWxpY2UxMjM="}}
{"ctrl":{"id":"80010","code":404,"text":"not found","ts":"2023-05-01T02:37:31.956Z"}}

Then you login as bob and it works. Then you attempt to subscribe to bob's me topic and the topic is not found on the server. You probably misconfigured something. Most likely the server is not creating accounts for your users.

This is your config:

        "rest": {
            "server_url": "http://demo-auth-server:5000/",
            "use_separate_endpoints": true
        },

This is the sample config from the readme:

  "rest": {
    // ServerUrl is the URL of the authentication server to call. The URL must be absolute:
    // it must include the scheme, such as http or https, and the host name.
    "server_url": "http://127.0.0.1:5000/",
    // Authentication server is allowed to create new accounts.
    "allow_new_accounts": true,
    // Use separate endpoints, i.e. add request name to serverUrl path when making requests:
    // http://127.0.0.1:5000/add
    "use_separate_endpoints": true
  },

Do you see the line "allow_new_accounts": true, in your config?

You still posted just a half of the client-side log.

There is no detailed logs, just sth like

You have the source code. You can add whatever logs you want.

pkuwwt commented 1 year ago

@or-else My mistake.

There is no error of "not found", only "user not found" triggered by init_topic: failed to load or create topic.

I have tried allow_new_accounts, nothing changed.

I guess what happened as follows:

  1. When I logged in as bob, the chat server requested route /auth from auth server and got the uid
  2. Then it tried to use this uid query user from database.
  3. When it found that there is no such user, it complained user not found in function init_topic.
  4. Even I enabled allow_new_accounts, no extra request was received by auth server
or-else commented 1 year ago

is your issue resolved now?

pkuwwt commented 1 year ago

@or-else No.

If my understanding is correct, then I think the rest auth is problematic.

or-else commented 1 year ago

I think the rest auth is problematic.

Maybe, but more likely that you are doing something incorrectly. If you think there is a bug, then please please debug it and let me know what you find.

or-else commented 1 year ago

then init_topic function should query user from rest auth server other than local database

That's not how it works. rest-auth responds with enough information to create a user account https://github.com/tinode/chat/blob/master/rest-auth/auth.py#L53

pkuwwt commented 1 year ago

@or-else I know the logic now.

If there is no uid in auth server response, and allow_new_accounts is enabled, then the auth server works.

If there is a uid in auth server response, and there is no user record in local database, then auth server does not work.

The users in the external auth server will be copied to the local database and generated a uid. The uid will be saved to auth server by /link endpoint.

So the fix will be: remove all uid in dummy_data.json .

or-else commented 1 year ago

If you found a bug, please send a pull request. Thanks.