social icon indicating copy to clipboard operation
social copied to clipboard

Cannot interact with others - UnauthorizedFediverseException

Open sylvainmetayer opened this issue 2 years ago • 1 comments

Describe the bug Everytime an external service tries to communicate with Social the messages cannot be processed and result in a UnauthorizedFediverseException

When I dig into the SignatureService while debugging to find the cause, I find that the exception thrown is the SignatureException

https://github.com/nextcloud/social/blob/c8bf03bf3f68f4203f102ecbeb3b482443e11c16/lib/Service/SignatureService.php#L360

This is a bug already mentioned in https://github.com/nextcloud/social/issues/375 and https://github.com/nextcloud/social/issues/269

The origin of the distant server is correctly detected, but for an unknown reason, the signature verification fails https://github.com/nextcloud/social/blob/c8bf03bf3f68f4203f102ecbeb3b482443e11c16/lib/Service/SignatureService.php#L399

My setup is the following :

  • VPS hosted on cloud provider
  • Nginx with domain and https
  • proxy to the nextcloud container (https://github.com/linuxserver/docker-nextcloud )
  • This container contains a nginx that proxy to PHP FPM
internet -> VPS -> nginx (443) -> nginx (linuxserver container on port 80) -> PHP

To Reproduce Steps to reproduce the behavior:

  1. Follow any account
  2. Wait for the server to ping back (in the /inbox endpoint)
  3. Check for SignatureException exception in the logs
  4. See error

Expected behavior

No SignatureException in the log.

You'll find in the details my nginx configuration, there is maybe an error with it, but I can't find it.

Client details:

  • OS: Windows / Linux (Fedora)
  • Browser Firefox 114
  • Version : Nextcloud Hub 5 (27.0.0)
  • Device: desktop
Server details

Social app version: 0.6.1

Operating system: Debian 11.7

Web server: nginx/1.18.0

Database: mysql Ver 15.1 Distrib 10.5.19-MariaDB, for debian-linux-gnu (x86_64) using EditLine wrapper

PHP version: PHP 8.2.7

Nextcloud version: Nextcloud Hub 5 (27.0.0)

Logs

Nextcloud log (data/nextcloud.log)

{"reqId":"zQnx9t9ps8FvFa8MqIEg","level":2,"time":"July 09, 2023 17:23:34","remoteAddr":"192.168.144.1","user":"--","app":"no app in context","method":"POST","url":"/index.phpal/inbox","message":"500 - {\"status\":-1,\"exception\":\"OCA\\\\Social\\\\Exceptions\\\\UnauthorizedFediverseException\",\"message\":\"Empty Origin\"}","userAgent":"http.rb/5.1.1 (Mastodon/4.1.4; +https://MASTODON_SERVER_URL/)","version":"27.0.0.8","data":[]}

Nginx configuration (443, with custom domain)

upstream nextcloud {
    server 127.0.0.1:9003;
}

server {
    listen 443 ssl http2;
    server_name NC_DOMAIN;
    root /var/www/default/;
    index index.php;
    client_max_body_size 1G;

    location = /robots.txt  { access_log off; log_not_found off; }
    location = /favicon.ico { access_log off; log_not_found off; }
    # Deny access to .htaccess files, if Apache's document root concurs with nginx's one
    location /.ht {
        deny  all;
    }

    # Deny access to hidden dotfiles (beginning with '.')
    location /. {
        deny all;
    }

    access_log  /var/log/nginx/NC_DOMAIN.access.log combined;
    error_log   /var/log/nginx/NC_DOMAIN.error.log;

    location / {
        include proxy_params;
        proxy_pass_request_headers      on;
        proxy_pass http://nextcloud;
    }

    # Make a regex exception for `/.well-known` so that clients can still
    # access it despite the existence of the regex rule
    # `location ~ /(\.|autotest|...)` which would otherwise handle requests
    # for `/.well-known`.
    location ^~ /.well-known {
        # The rules in this block are an adaptation of the rules
        # in `.htaccess` that concern `/.well-known`.

        location = /.well-known/carddav { return 301 /remote.php/dav/; }
        location = /.well-known/caldav  { return 301 /remote.php/dav/; }
        #location = /.well-known/webfinger  { return 301 /public.php?service=webfinger; }

        location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
        location /.well-known/pki-validation    { try_files $uri $uri/ =404; }

        # Anything else is dynamically handled by Nextcloud
        location ^~ /.well-known            { return 301 $scheme://$host/index.php$uri$is_args$args; }

        try_files $uri $uri/ =404;
    }


    # https://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/
    # Send cert validity information ourselves, so the user does not have to ask the CA (who
    # then knows the user visited the website).
    # Test with openssl s_client -connect www.example.com:443 -servername www.example.com -status < /dev/null | grep OCSP
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 1.1.1.1;

    # https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=modern&openssl=1.1.1d&hsts=false&guideline=5.6
    ssl_certificate         /etc/letsencrypt/live/NC_DOMAIN/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/NC_DOMAIN/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/NC_DOMAIN/chain.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # modern configuration
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;
}

server {
    listen 80;
    server_name NC_DOMAIN;
    return 301 https://$host$request_uri;
}

Nginx configuration (from linux server container)

## Version 2023/06/23 - Changelog: https://github.com/linuxserver/docker-nextcloud/commits/master/root/defaults/nginx/site-confs/default.conf.sample

# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
    "" "";
    default "immutable";
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;

    server_name _;

    include /config/nginx/ssl.conf;

    root /app/www/public;

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;


    # display real ip in nginx logs when connected through reverse proxy via docker network
    set_real_ip_from 172.16.0.0/12;
    real_ip_header X-Forwarded-For;

    # https://docs.nextcloud.com/server/latest/admin_manual/installation/nginx.html#nextcloud-in-the-webroot-of-nginx

    # set max upload size and increase upload timeout:
    client_max_body_size 1G;
    client_body_timeout 300s;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    # Pagespeed is not supported by Nextcloud, so if your server is built
    # with the `ngx_pagespeed` module, uncomment this line to disable it.
    #pagespeed off;

    # The settings allows you to optimize the HTTP2 bandwitdth.
    # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
    # for tunning hints
    client_body_buffer_size 512k;

    # HTTP response headers borrowed from Nextcloud `.htaccess`
    add_header Referrer-Policy                      "no-referrer"       always;
    add_header X-Content-Type-Options               "nosniff"           always;
    add_header X-Download-Options                   "noopen"            always;
    add_header X-Frame-Options                      "SAMEORIGIN"        always;
    add_header X-Permitted-Cross-Domain-Policies    "none"              always;
    add_header X-Robots-Tag                         "noindex, nofollow" always;
    add_header X-XSS-Protection                     "1; mode=block"     always;

    # Remove X-Powered-By, which is an information leak
    fastcgi_hide_header X-Powered-By;

    # Specify how to handle directories -- specifying `/index.php$request_uri`
    # here as the fallback means that Nginx always exhibits the desired behaviour
    # when a client requests a path that corresponds to a directory that exists
    # on the server. In particular, if that directory contains an index.php file,
    # that file is correctly served; if it doesn't, then the request is passed to
    # the front-end controller. This consistent behaviour means that we don't need
    # to specify custom rules for certain paths (e.g. images and other assets,
    # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
    # `try_files $uri $uri/ /index.php$request_uri`
    # always provides the desired behaviour.
    index index.php index.html /index.php$request_uri;

    # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
    location = / {
        if ( $http_user_agent ~ ^DavClnt ) {
            return 302 /remote.php/webdav/$is_args$args;
        }
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    #rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
    # Make a regex exception for `/.well-known` so that clients can still
    # access it despite the existence of the regex rule
    # `location ~ /(\.|autotest|...)` which would otherwise handle requests
    # for `/.well-known`.
    location ^~ /.well-known {
        # The rules in this block are an adaptation of the rules
        # in `.htaccess` that concern `/.well-known`.

        location = /.well-known/carddav { return 301 /remote.php/dav/; }
        location = /.well-known/caldav  { return 301 /remote.php/dav/; }
        #location = /.well-known/webfinger  { return 301 /public.php?service=webfinger; }

        location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
        location /.well-known/pki-validation    { try_files $uri $uri/ =404; }

        # Anything else is dynamically handled by Nextcloud
        location ^~ /.well-known            { return 301 $scheme://$host/index.php$uri; }

        try_files $uri $uri/ =404;
        # return 301 /index.php$request_uri;
    }

    # Rules borrowed from `.htaccess` to hide certain paths from clients
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)                { return 404; }

    # Ensure this block, which passes PHP files to the PHP process, is above the blocks
    # which handle static assets (as seen below). If this block is not declared first,
    # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
    # to the URI, resulting in a HTTP 500 error response.
    location ~ \.php(?:$|/) {
        # Required for legacy support
        rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;

        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        set $path_info $fastcgi_path_info;

        try_files $fastcgi_script_name =404;

        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $path_info;

        fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass 127.0.0.1:9000;

        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;

        fastcgi_max_temp_file_size 0;
    }

    location ~ \.(?:css|js|svg|gif|png|jpg|ico|wasm|tflite|map)$ {
        try_files $uri /index.php$request_uri;
        add_header Cache-Control "public, max-age=15778463, $asset_immutable";
        access_log off;     # Optional: Don't log access to assets

        location ~ \.wasm$ {
            default_type application/wasm;
        }
    }

    location ~ \.woff2?$ {
        try_files $uri /index.php$request_uri;
        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    # Rule borrowed from `.htaccess`
    location /remote {
        return 301 /remote.php$request_uri;
    }

    location / {
        # enable for basic auth
        #auth_basic "Restricted";
        #auth_basic_user_file /config/nginx/.htpasswd;

        try_files $uri $uri/ /index.php$request_uri;
    }

    # deny access to .htaccess/.htpasswd files
    location ~ /\.ht {
        deny all;
    }

    # https://help.nextcloud.com/t/warning-rainloop-data-folder-is-accessible/33033/2
    location ^~ /apps/rainloop/app/data {
        deny all;
    }
}

sylvainmetayer avatar Jul 09 '23 15:07 sylvainmetayer

Same issue in Nextcloud 30.0.3 using the current git sources, webfinger.net can access accounts, but the POST to `/index.php/apps/social/inbox' gets a 500 error and throws UnauthorizedFediverseException

This is running Debian 12 on an rpi5, also running PixelFed, WP and Mobilizon on the fediverse without issue. NC is a manual install, no proxy, just Apache2 with PHP-FPM. This was also working before the upgrade from NC-29

teledyn avatar Dec 10 '24 00:12 teledyn