Giter Site home page Giter Site logo

matrix-user-verification-service's Introduction

Matrix User Verification Service

Service to verify details of a user based on an Open ID Connect token.

Main features:

  • Verifies a C2S Open ID token using the S2S UserInfo endpoint.
  • Can verify user is a member in a given room (Synapse only currently, requires admin level token). In addition to returning membership status, returned will be user power level, the room power defaults and required power for events.

How to use

Dependencies

npm install

Configuration

Copy the default .env.default to .env and modify as needed.

## REQUIRED
# Homeserver client API admin token (synapse only)
# Required for the service to verify room membership
UVS_ACCESS_TOKEN=foobar
# Homeserver client API URL
UVS_HOMESERVER_URL=https://matrix.org
# Disable check for non private IP range of homeserver. E.g. set to `true` if your homeserver domain resolves to a private IP.
UVS_DISABLE_IP_BLACKLIST=true

## OPTIONAL
# Auth token to protect the API
# If this is set any calls to the provided API endpoints
# need have the header "Authorization: Bearer changeme".
UVS_AUTH_TOKEN=changeme
# Matrix server name to verify OpenID tokens against. See below section.
# Defaults to empty value which means verification is made against
# whatever Matrix server name passed in with the token.
UVS_OPENID_VERIFY_SERVER_NAME=matrix.org
# Listen address of the bot
UVS_LISTEN_ADDRESS=127.0.0.1
# Listen port of the bot
UVS_PORT=3000
# Log level, defaults to 'info'
# See choices here: https://github.com/winstonjs/winston#logging-levels
UVS_LOG_LEVEL=info

OpenID token verification

UVS can run in a single homeserver mode or be configured to trust any homeserver OpenID token. Default is to trust the any Matrix server name that is given with the OpenID token.

To disable this and ensure only OpenID tokens from a single Matrix homeserver will be trusted, set the homeserver Matrix server name in the variable UVS_OPENID_VERIFY_SERVER_NAME. Note, this is the server name of the homeserver, not the client or federation API's domain.

In either mode, the UserInfo endpoint is determined by resolving server names in the usual way so a /.well-known/matrix/server file may be needed even if the homeserver isn't otherwise federating. If the homeserver config doesn't have the federation listener setup, the openid listener can be added on the same port as the client listener.

Room membership is still currently limited to be verified from a single configured homeserver client API via UVS_HOMESERVER_URL.

API's available

Authentication

If UVS_AUTH_TOKEN is set, you'll need to provide an authorization header as follows:

Authorization: Bearer <value of UVS_AUTH_TOKEN>

Verify OpenID token

Verifies a user OpenID token.

POST /verify/user
Content-Type: application/json

Request body:

{
  "matrix_server_name": "domain.tld",
  "token": "secret OpenID token provided by the user"
}

Successful validation response:

{
  "results": {
    "user": true
  },
  "user_id": "@user:domain.tld"
}

Failed validation:

{
  "results": {
    "user": false
  },
  "user_id": null
}

Verify OpenID token and room membership

Verifies a user OpenID token and membership in a room.

POST /verify/user_in_room
Content-Type: application/json

Request body:

{
  "matrix_server_name": "domain.tld",
  "room_id": "!foobar:domain.tld",
  "token": "secret OpenID token provided by the user"
}

Successful validation response:

{
  "results": {
    "room_membership": true,
    "user": true
  },
  "user_id": "@user:domain.tld",
  "power_levels": {
    "room": {
      "ban": 50,
      "events": {
        "m.room.avatar": 50,
        "m.room.canonical_alias": 50,
        "m.room.history_visibility": 100,
        "m.room.name": 50,
        "m.room.power_levels": 100
      },
      "events_default": 0,
      "invite": 0,
      "kick": 50,
      "redact": 50,
      "state_default": 50,
      "users_default": 0
    },
    "user": 50
  }
}

Failed validation, in case token is not valid:

{
  "results": {
    "room_membership": false,
    "user": false
  },
  "user_id": null,
  "power_levels": null
}

In the token was validated but user is not in room, the failed response is:

{
  "results": {
    "room_membership": false,
    "user": true
  },
  "user_id": "@user:domain.tld",
  "power_levels": null
}

Running

npm start

Development

Run in watch mode.

npm run dev

License

Apache 2.0

matrix-user-verification-service's People

Contributors

benbz avatar half-shot avatar jakicoll avatar jaywink avatar mm28ajos avatar skolmer avatar thermaq avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

matrix-user-verification-service's Issues

Support verifying against a homeserver that's using self-signed certificates

It should be possible to configure via an environment variable, UVS_DISABLE_CERTIFICATE_VERIFICATION, that when set to false will cause any axios.get calls to no longer fail if the server's SSL certificate cannot be verified. Mostly for local testing use-cases.

Such an option should come with a warning, especially if the UVS and the homeserver are on separate computers (as a Synapse admin access token is passed in the request).


The way to disable certificate verification checking with axios is:

    const axios = require('axios');
    const https = require('https');
    
    // ...

    const agent = new https.Agent({
        rejectUnauthorized: false,
        requestCert: false,
        agent: false,
     });

    const response = await axios.get(
        url,
        {
            headers,
            maxRedirects: 0,
            timeout: 10000,
            validateStatus: function (status) {
                // Include redirects as OK here, since we control that separately
                return status >= 200 && status < 400;
            },
            httpsAgent: agent,
        },
    )

Support users on other Matrix servers

Currently the verification service requires the Matrix server that the user token is created with and the Synapse it verifies room membership against to be the same. This restriction could be lifted by passing in the Matrix server name to verify the token against.

Allow verifying room membership against multiple Synapse instances

Currently only a single Synapse homeserver URL and admin access token can be configured per instance of matrix-user-verification-service. However, in a deployment that features multiple, federated homeservers but only a single Jitsi cluster, one would need to verify room membership of users across multiple servers.

As the prosody module is passed the homeserver domain name in each verification request, we could query multiple homeservers, as long as each are configured.

This issue proposes a mechanism for allowing verification of both a user's registration as well as their participation in a room across multiple homeservers with only a single instance of the matrix-user-verification-service.


Currently homeserver credentials are configured through the use of environment variables. UVS_HOMESERVER_URL is the URL of the homeserver to verify against, while UVS_ACCESS_TOKEN is the access token of a Synapse admin user. The matrix-user-verification-service will then call GET {UVS_HOMESERVER_URL}/_synapse/admin/v1/rooms/{ROOM_ID}/state with the admin access token in order to check the state of the room and whether the user is currently present.

There are many ways to alter this configuration to allow multiple homeservers. One such solution is to provide an additional environment variable, i.e:

UVS_VERIFY_ROOM_MEMBERSHIP_HOMESERVERS=domain1.name:admin_access_token1;domain2.name:admin_access_token2...

which the matrix-user-verification-service would then use when fielding POST /verify/user_in_room requests from the mod_matrix_power_sync prosody module.

Note that in the above deployment scenario, one should not set UVS_OPENID_VERIFY_SERVER_NAME. This will cause the matrix-user-verification-service to verify OpenID tokens (ensuring that a user exists on the homeserver) against any requested homeserver, rather than just the one specified by UVS_OPENID_VERIFY_SERVER_NAME.

isDomainBlacklisted function seems confusingly named

async function isDomainBlacklisted(domain) {

If I'm reading it correctly, it seems to check if IP addresses are blacklisted (rather than domains), and returns true if the domain doesn't resolve (which isn't the same thing as being blacklisted).

I could be reading it wrong though, I'm a horrible software developer :P

At the moment though it seems like UVS generates some confusing error messages about blacklisted IPs when it just can't resolve the DNS.

Any changes required in homeserver.yaml?

It is not clear from the documentation whether any changes need to be made in /etc/matrix-synapse/homeserver.yaml

For instance the Readme suggests .env to have UVS_ACCESS_TOKEN=foobar. Should this 'foobar' token be also added in /etc/matrix-synapse/homeserver.yaml ?

discoverHomeserverUrl Edgecase

Edge case somewhere in matrixUtils.js:async function discoverHomeserverUrl(serverName)

My synapse server has delegation with the port 443, and the wellknown entry returns:

{ "m.server": "matrix.domain.tld:443" }

yet matrixUtils.js:54 somehow returns domain.tld:8448.

the .env entry also being: UVS_OPENID_VERIFY_SERVER_NAME=domain.tld

Well-known lookups should be cached

When running in multiple homeserver mode, we do well-known lookups to resolve homeserver URL's, as per Matrix S2S spec.

These well-known lookups should be cached for some period of time for performance and stability reasons, and to avoid hammering remote web servers.

Clarifying the readme

Hey, I'm having a hard time understanding what's needed to get everything configured:

UVS_ACCESS_TOKEN=syt_foobar ###### foobar is confusing, should this be the access token for an admin user made specifically for this service?
UVS_HOMESERVER_URL=synapse:8008 ###### does this need to be https://matrix.domain.tld # or can it be as shown, since it resides in the same docker network

## OPTIONAL
# Auth token to protect the API
# If this is set any calls to the provided API endpoints
# need have the header "Authorization: Bearer changeme". ###### need to have the header where? do I need to add something here or can this be the same as UVS_ACCESS_TOKEN? The api endpoint is filtered by the proxy, so going directly to synapse:8008 should work. Can it be determined in homeserver.yaml if UVS_AUTH_TOKEN is required here?
UVS_AUTH_TOKEN=syt_foobar ###### add syt_ to reduce confusion
UVS_OPENID_VERIFY_SERVER_NAME=matrix.domain.tld ###### what's this? `curl https://matrix.domain.tld/.well-known/matrix/client`, is it m.homeserver -> base_url? Or is it server_name from homeserver.yaml?

UVS_LISTEN_ADDRESS=0.0.0.0 ###### I'm guessing this is required if UVS needs to be opened to the outside world?
UVS_LOG_LEVEL=debug ###### I'm not seeing any logs still

@jaywink Can you elaborate please?

[NOT AN ISSUE BUT HELP NEEDED]

I am not able to understand the README file completely. I am not able to understand which env variables to be taken and what should be their values. I am attaching the .env file as I understood . Kindly review and guide me

UVS_ACCESS_TOKEN=foobar
UVS_HOMESERVER_URL=https://matrix.org
UVS_LISTEN_ADDRESS=127.0.0.1
UVS_PORT=3000
UVS_LOG_LEVEL=info
UVS_OPENID_VERIFY_ANY_HOMESERVER=false
UVS_DISABLE_IP_BLACKLIST=true
UVS_AUTH_TOKEN=yash
UVS_OPENID_VERIFY_SERVER_NAME=matrix.org

I made this request body

{
  "matrix_server_name": "matrix.org",
  "token": "foobar"
}

Something is wrong with UVS_DISABLE_IP_BLACKLIST=true

Code diving didn't do me much good, I just went on and:

diff --git a/src/utils.js b/src/utils.js
index fa18820..f657e5a 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -92,7 +92,6 @@ function requestLogger(req) {

 const ip4RangeBlacklist = [
     '127.0.0.0/8',
-    '10.0.0.0/8',
     '172.16.0.0/12',
     '192.168.0.0/16',
     '100.64.0.0/10',

And voila, I didn't get the host is blacklisted error anymore. This is obviously not a solution, but someone with more experience on this code should give it a look.

Handling of Home Server with Private IP

Describe the bug
UVS not working if using private ip-range, e.g.. docker net, to contact matrix synapse home server.

To Reproduce
Steps to reproduce the behavior:

  1. Deploy UVS and synapse with docker in the same docker net.
  2. Set .env homeserver variable to point to docker net host name of synapse.
  3. Run verification request to USV.

Expected behavior
USV contacts synapse by docker net and retrieves room result.

Additional context
If using the UVS only within your own network e.g. to allow jitsi prosody to authenticate matrix users to use jitsi, you do not have to expose the admin API of synapse outside your local network i.e. the admin API of synapse must only be accessible by the docker host but not e.g. by hosts on the internet behind a reverse proxy. However, this setup does not work with USV as home server domains, which resolve to private ip addresses, are not accepted by UVS. Removing the blacklisting of private ip ranges or allowing to switch of the check might be a solution?

Access Service under Port 3000 in Docker Image not Possible

I tried to setup this docker image on our docker server on which docker and jitsi is running. i added this to the docker-compose file.

  matrix-user-verification-service:
    depends_on:
      - synapse
    image: matrixdotorg/matrix-user-verification-service:branch-master
    restart: unless-stopped
    networks:
      - matrix
    ports:
      - 3000:3000
    environment:
      - UVS_ACCESS_TOKEN
      - UVS_HOMESERVER_URL
      - UVS_DISABLE_IP_BLACKLIST
      - UVS_LISTEN_ADDRESS
      - UVS_OPENID_VERIFY_SERVER_NAME
      - UVS_PORT
      - UVS_LOG_LEVEL

To the ENV Konfiguration (I Use Portainer) i added:
UVS_ACCESS_TOKEN = sometoken
UVS_HOMESERVER_URL = https://matrix.domain.com
UVS_DISABLE_IP_BLACKLIST = true
UVS_OPENID_VERIFY_SERVER_NAME = matrix.domain.com
UVS_LOG_LEVEL = debug

I see that now something is running under port "3000" but connect to it is not possible.

root@srv01:/data/docker-data# nc localhost 3000
POST /verify/user
root@srv01:/data/docker-data#

The same when i first try to set "Authorization: Bearer sometoken" after connect.

The docker log file only show's me

> [email protected] start /app
> node src/app.js
{
  level: 'info',
  message: 'Attempting to listen on 127.0.0.1:3000',
  timestamp: '2023-01-04T11:46:04.224Z'
}
{
  level: 'info',
  message: 'Verify user service listening at 127.0.0.1:3000',
  timestamp: '2023-01-04T11:46:04.229Z'
}

and no connection attempt. Do i something wrong with my configuration?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.