haiwen / seafile

High performance file syncing and sharing, with also Markdown WYSIWYG editing, Wiki, file label and other knowledge management features.
http://seafile.com/
Other
12.25k stars 1.54k forks source link

[BUG] 2FA Client redirect autologin broken (subdomain) #1900

Closed soakes closed 5 years ago

soakes commented 7 years ago

Hi Guys,

I believe I have just found a bug when using the client to log you into the site if your running under sub folder setup with 2FA enabled for that user.

If you goto https://example.com/seafile, it all works as expected. The client login (i.e. click on domain name inside the client which also directs you to this URL) works correctly if you do not use 2FA.

If you try the same but enable 2FA (google auth), the login fails with page cant be found (Sorry, but the requested page could not be found.). The URL it try's to send you to is, https://example.com/seafile/seafile which is clearly wrong.

This config is exactly the same with and without 2FA and as long as you don't use 2FA, then the login works correctly. The sub folder config has also been taken from your website/docs.

I can only suspect its something to do with the 2FA auth check on the client when the client logs you in. I can confirm that the 2FA login via website or the initial client login is working as expected (i.e. asking for 2FA details). This bug is only present if your logged in on the client and your using it to automatically log you into the website i.e. clicking on domain/auto login within client. If you right click and copy location on the client, it shows correct i.e. https://example.com/seafile.

I can confirm that this is present with the latest seafile-pro-server-6.0.13 and also the MacOS client version 6.04, which as of this writing are both the latest available.

I have also just confirmed this on the latest Windows client.

Hope this information is of use.

As a TEMP solution, I am disabling 2FA auth, just to fix the problem.

I am also enclosing the nginx and seahub_settings.py configs, just in case the problem is me which I don't think it its.

nginx config

# Virtual Host configuration
# Letsencrypt
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
server {
  listen                80;
  server_name           example.com;
  root          /usr/share/nginx/html;

  # Necessary for Let's Encrypt Domain Name ownership validation
  location /.well-known/acme-challenge/ {
    try_files $uri /dev/null =404;
  }

  location / {
    return 301 https://$host$request_uri;
  }

}

server {
  listen 443;
  server_name  "example.com";
  ssl on;
  ssl_certificate /etc/ssl/letsencrypt/example.com-pem;
  ssl_certificate_key /etc/ssl/letsencrypt/example.com-key;

  root          /usr/share/nginx/html;

  proxy_set_header X-Forwarded-For $remote_addr;
  location /seafile {
    fastcgi_pass    127.0.0.1:8000;
    fastcgi_param   SCRIPT_FILENAME     $document_root$fastcgi_script_name;
    fastcgi_param   PATH_INFO           $fastcgi_script_name;
    fastcgi_param   SERVER_PROTOCOL     $server_protocol;
    fastcgi_param   QUERY_STRING        $query_string;
    fastcgi_param   REQUEST_METHOD      $request_method;
    fastcgi_param   CONTENT_TYPE        $content_type;
    fastcgi_param   CONTENT_LENGTH      $content_length;
    fastcgi_param   SERVER_ADDR         $server_addr;
    fastcgi_param   SERVER_PORT         $server_port;
    fastcgi_param   SERVER_NAME         $server_name;
    fastcgi_param   REMOTE_ADDR         $remote_addr;
    fastcgi_param   HTTPS               on;
    fastcgi_param   HTTP_SCHEME         https;
    access_log      /var/log/nginx/seahub.access.log;
    error_log       /var/log/nginx/seahub.error.log;
  }
  location /seafhttp {
    rewrite ^/seafhttp(.*)$ $1 break;
    proxy_pass http://127.0.0.1:8082;
    client_max_body_size 0;
    proxy_connect_timeout  36000s;
    proxy_read_timeout  36000s;
    proxy_send_timeout  36000s;
  }
  location /media {
    root /usr/local/share/seafile/seafile-server-latest/seahub;
  }
  location /seafdav {
    fastcgi_pass    127.0.0.1:8080;
    fastcgi_param   SCRIPT_FILENAME     $document_root$fastcgi_script_name;
    fastcgi_param   PATH_INFO           $fastcgi_script_name;
    fastcgi_param   SERVER_PROTOCOL     $server_protocol;
    fastcgi_param   QUERY_STRING        $query_string;
    fastcgi_param   REQUEST_METHOD      $request_method;
    fastcgi_param   CONTENT_TYPE        $content_type;
    fastcgi_param   CONTENT_LENGTH      $content_length;
    fastcgi_param   SERVER_ADDR         $server_addr;
    fastcgi_param   SERVER_PORT         $server_port;
    fastcgi_param   SERVER_NAME         $server_name;
    fastcgi_param   REMOTE_ADDR         $remote_addr;
    fastcgi_param   HTTPS               on;
    client_max_body_size 0;
    access_log      /var/log/nginx/seafdav.access.log;
    error_log       /var/log/nginx/seafdav.error.log;
  }
}

ccnet.conf

[General]
USER_NAME = seafile
ID = **********************
NAME = seafile
SERVICE_URL = https://example.com/seafile/

[Client]
PORT = 13419

[Database]
ENGINE = mysql
HOST = 127.0.0.1
PORT = 3306
USER = seafile
PASSWD = **************************
DB = ccnet-db
CONNECTION_CHARSET = utf8

seahub_settings.py

# -*- coding: utf-8 -*-
SECRET_KEY = "*******************************************"

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'seahub-db',
        'USER': 'seafile',
        'PASSWORD': 'Lo56CYhDJ2V7blqaEiOT',
        'HOST': '127.0.0.1',
        'PORT': '3306'
    }
}

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

# Enable 2FA
ENABLE_TWO_FACTOR_AUTH = True

# Enable cloude mode and hide Organization tab.
CLOUD_MODE = True

# Enalbe registration on web.
ENABLE_SIGNUP = False

# Email configuration
EMAIL_USE_TLS = True
EMAIL_HOST = 'mail.example.com'        # smpt server
EMAIL_HOST_USER = 'seafile@example.com'    # username and domain
EMAIL_HOST_PASSWORD = '*************'    # password
EMAIL_PORT = '587'
DEFAULT_FROM_EMAIL = 'no-reply@example.com'
SERVER_EMAIL = 'no-reply@example.com'

# enable resumimg of uploads
ENABLE_RESUMABLE_FILEUPLOAD = True

FILE_SERVER_ROOT = 'https://example.com/seafhttp'

# sub folder
SERVE_STATIC = False
MEDIA_URL = '/media/'
COMPRESS_URL = MEDIA_URL
STATIC_URL = MEDIA_URL + 'assets/'
SITE_ROOT = '/seafile/'
LOGIN_URL = '/seafile/accounts/login/'    # NOTE: since version 5.0.4
soakes commented 7 years ago

Quick update.

After doing some further testing, I now can confirm that this issue isn't present using just a sub domain.

2FA is working correctly with the client and logging into site as long as its setup as a subdomain and not folder.

Miller101 commented 7 years ago

Hi :)

How about changing the https redirect directive to: return 301 https://$server_name$request_uri;

Not sure about this, but: I'm not using the --- root /usr/share/nginx/html; Variable at all as i'm redirecting anything anyways Could you try to remove them out of the http and https directive?

Additional help: https://www.bjornjohansen.no/nginx-redirect

There you can find a bunch of very good examples for redirecting. Let's see if that helps.

Let me know if any of this worked :) Greets

soakes commented 7 years ago

Hi @Miller101,

Thank you very much for the suggestion and that truly awesome website.

The reason for the root is so letsencrypt can create the initial and renewal certificates as it creates the .well-known hash files in there to authenticate. However, I do agree that usually you would not need it however, you have to remember that you don't want EVERYTHING redirected to SSL as the http://example.com/.well-known/acme-challenge/HASHFILE needs to be accessible without https as thats whats used to confirm the owner of the domain.

With regards to testing it, that won't be so easy as that server has been changed to subdomain and is now in LIVE service. I will see if I get a little time over the weekend and knock up a quick box and re-test all the suggestions that you have supplied so we and everyone else knows the exact solution.

Kind Regards,

Simon