Bubka / 2FAuth

A Web app to manage your Two-Factor Authentication (2FA) accounts and generate their security codes
https://docs.2fauth.app/
GNU Affero General Public License v3.0
2.3k stars 152 forks source link

Can't get https to work #356

Closed justinh998 closed 2 months ago

justinh998 commented 4 months ago

Version

v5.2.0

Details & Steps to reproduce

Hello,

I am currently trying to get fauth2 to work somehow via HTTPS.

Firstly, I created a domain that points to the IP of my machine with 2fauth (in my case with Cloudflare). I then entered this domain in the Docker Compose configuration of 2fauth including HTTPS was entered.

I realised that certificates for the domain were apparently missing. However, I could not find a way to store these certificates in 2fauth. This of course meant that the website was not loaded by my browser because SSL certificates were missing. So I finally gave up this way and assumed that 2fauth probably does not support secure connections.

I then tried using a reverse proxy (Cloudflared in my case(claudfared creates a claudfare tunnel through which the data is sent and cloudfare then takes care of the certificates, so I don't have to keep renewing them) ) and realised that I was getting a "mixed content" warning and my browser was refusing to load the page.

I then started googling and came across this issue that describes my problem. There it is suggested to set TRUSTED_PROXIES=* and to enter ASSET_URL=https://otp.xxxx.ch (this solution seems to have worked for many users). I did this, but without success, as I already realised in step 1 that a secure connection is probably not supported. I didn't get any more "mixed content" warnings, but instead I got a lot of ERR_SSL_PROTOCOL_ERROR (as in step 1).

Error & Logs

There is nothing really interesting in the logs for my problem case (2fauth works perfectly via http).

Execution environment

I have deployed 2fauth via Docker Compose on Docker. Here is my Docker Compose configuration:

version: "3"
services:
  2fauth:
    image: 2fauth/2fauth
    container_name: 2fauth
    volumes:
      - ./2fauth:/root
    ports:
      - 8001:8000/tcp
    restart: unless-stopped
    environment:
      # You can change the name of the app
      - APP_NAME=2FAuth
      # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation.
      # Never set it to "testing".
      - APP_ENV=local
      # The timezone for your application, which is used to record dates and times to database. This global setting can be
      # overridden by users via in-app settings for a personalised dates and times display.
      # If this setting is changed while the application is already running, existing records in the database won't be updated
      - APP_TIMEZONE=UTC
      # Set to true if you want to see debug information in error screens.
      - APP_DEBUG=true
      # This should be your email address
      - SITE_OWNER=mymail@gmail.com
      # The encryption key for  our database and sessions. Keep this very secure.
      # If you generate a new one all existing data must be considered LOST.
      # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
      - APP_KEY=base64:O/bBih0ZagiDPT/EV91m7v+N2b4dPzpj7iIRxOPxQ14=
      # This variable must match your installation's external address.
      # Webauthn won't work otherwise.
      - APP_URL=publicipofmymachine:8001
      # If you want to serve js assets from a CDN (like https://cdn.example.com),
      # uncomment the following line and set this var with the CDN url.
      # Otherwise, let this line commented.
      - ASSET_URL=same as app_url:8001
      #
      # Turn this to true if you want your app to react like a demo.
      # The Demo mode reset the app content every hours and set a generic demo user.
      - IS_DEMO_APP=false
      # The log channel defines where your log entries go to.
      # 'daily' is the default logging mode giving you 7 daily rotated log files in /storage/logs/.
      # Also available are 'errorlog', 'syslog', 'stderr', 'papertrail', 'slack' and a 'stack' channel
      # to combine multiple channels into a single one.
      - LOG_CHANNEL=daily
      # Log level. You can set this from least severe to most severe:
      # debug, info, notice, warning, error, critical, alert, emergency
      # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
      # nothing will get logged, ever.
      - LOG_LEVEL=notice
      # Database config (can only be sqlite)
      - DB_DATABASE="/srv/database/database.sqlite"
      # If you're looking for performance improvements, you could install memcached.
      - CACHE_DRIVER=file
      - SESSION_DRIVER=file
      # Mail settings
      # Refer your email provider documentation to configure your mail settings
      # Set a value for every available setting to avoid issue
      - MAIL_MAILER=log
      - MAIL_HOST=smtp.gmail.com
      - MAIL_PORT=587
      - MAIL_USERNAME="mymalil@gmail.com"
      - MAIL_PASSWORD="mypassword"
      - MAIL_ENCRYPTION=TLS
      - MAIL_FROM_NAME=myname
      - MAIL_FROM_ADDRESS="mymail@gmail.com"
      # SSL peer verification.
      # Set this to false to disable the SSL certificate validation.
      # WARNING
      # Disabling peer verification can result in a major security flaw.
      # Change it only if you know what you're doing.
      - MAIL_VERIFY_SSL_PEER=true
      # API settings
      # The maximum number of API calls in a minute from the same IP.
      # Once reached, all requests from this IP will be rejected until the minute has elapsed.
      # Set to null to disable the API throttling.
      - THROTTLE_API=60
      # Authentication settings
      # The number of times per minute a user can fail to log in before being locked out.
      # Once reached, all login attempts will be rejected until the minute has elapsed.
      # This setting applies to both email/password and webauthn login attemps.
      - LOGIN_THROTTLE=5
      # The default authentication guard
      # Supported:
      #   'web-guard' : The Laravel built-in auth system (default if nulled)
      #   'reverse-proxy-guard' : When 2FAuth is deployed behind a reverse-proxy that handle authentication
      # WARNING
      # When using 'reverse-proxy-guard' 2FAuth only look for the dedicated headers and skip all other built-in
      # authentication checks. That means your proxy is fully responsible of the authentication process, 2FAuth will
      # trust him as long as headers are presents.
      - AUTHENTICATION_GUARD=web-guard
      # Authentication log retention time, in days.
      # Log entries older than that are automatically deleted.
      - AUTHENTICATION_LOG_RETENTION=365
      # Name of the HTTP headers sent by the reverse proxy that identifies the authenticated user at proxy level.
      # Check your proxy documentation to find out how these headers are named (i.e 'REMOTE_USER', 'REMOTE_EMAIL', etc...)
      # (only relevant when AUTHENTICATION_GUARD is set to 'reverse-proxy-guard')
      - AUTH_PROXY_HEADER_FOR_USER=null
      - AUTH_PROXY_HEADER_FOR_EMAIL=null
      # Custom logout URL to open when using an auth proxy.
      - PROXY_LOGOUT_URL=null
      # WebAuthn settings
      # Relying Party name, aka the name of the application. If blank, defaults to APP_NAME. Do not set to null.
      - WEBAUTHN_NAME=2FAuth
      # Relying Party ID, should equal the site domain (i.e 2fauth.example.com).
      # If null, the device will fill it internally (recommended)
      # See https://webauthn-doc.spomky-labs.com/prerequisites/the-relying-party#how-to-determine-the-relying-party-id
      - WEBAUTHN_ID=null
      # Use this setting to control how user verification behave during the
      # WebAuthn authentication flow.
      #
      # Most authenticators and smartphones will ask the user to actively verify
      # themselves for log in. For example, through a touch plus pin code,
      # password entry, or biometric recognition (e.g., presenting a fingerprint).
      # The intent is to distinguish one user from any other.
      #
      # Supported:
      #   'required': Will ALWAYS ask for user verification
      #   'preferred' (default) : Will ask for user verification IF POSSIBLE
      #   'discouraged' : Will NOT ask for user verification (for example, to minimize disruption to the user interaction flow)
      - WEBAUTHN_USER_VERIFICATION=preferred
      #### SSO settings (for Socialite) ####
      # Uncomment and complete lines for the OAuth providers you want to enable.
      # - OPENID_AUTHORIZE_URL=
      # - OPENID_TOKEN_URL=
      # - OPENID_USERINFO_URL=
      # - OPENID_CLIENT_ID=
      # - OPENID_CLIENT_SECRET=
      # - GITHUB_CLIENT_ID=
      # - GITHUB_CLIENT_SECRET=
      # Use this setting to declare trusted proxied.
      # Supported:
      #   '*': to trust any proxy
      #   A comma separated IP list: The list of proxies IP to trust
      - TRUSTED_PROXIES='*'
      # Proxy for outgoing requests like new releases detection or logo fetching.
      # You can provide a proxy URL that contains a scheme, username, and password.
      # For example, "http://username:password@192.168.16.1:10".
      - PROXY_FOR_OUTGOING_REQUESTS=null
      # Leave the following configuration vars as is.
      # Unless you like to tinker and know what you're doing.
      - BROADCAST_DRIVER=log
      - QUEUE_DRIVER=sync
      - SESSION_LIFETIME=120
      - REDIS_HOST=127.0.0.1
      - REDIS_PASSWORD=null
      - REDIS_PORT=6379
      - PUSHER_APP_ID=
      - PUSHER_APP_KEY=
      - PUSHER_APP_SECRET=
      - PUSHER_APP_CLUSTER=mt1
      - VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
      - VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
      - MIX_ENV=local

Does anyone else have an idea what I'm doing wrong here?

kamalmjt commented 4 months ago

If you use SSL please set APP_URL=https://2fa.example.com and after please run thease comands in docker container to clear caches.

docker exec -it 2FAuth bash

after inside container change to 2fa app directory common is: cd /var/www/2fa/ and next run these commands to clear cache. sudo -u www-data php artisan config:clear sudo -u www-data php artisan config:cache sudo -u www-data php artisan route:clear sudo -u www-data php artisan view:cache sudo -u www-data php artisan optimize:clear

justinh998 commented 4 months ago

If you use SSL please set APP_URL=https://2fa.example.com and after please run thease comands in docker container to clear caches.

docker exec -it 2FAuth bash

after inside container change to 2fa app directory common is: cd /var/www/2fa/ and next run these commands to clear cache. sudo -u www-data php artisan config:clear sudo -u www-data php artisan config:cache sudo -u www-data php artisan route:clear sudo -u www-data php artisan view:cache sudo -u www-data php artisan optimize:clear

Thanks I will try it later, but I would still be interested to know why I should set the app url (where the external address of my server should be) to a non-existent address? I have also looked in the code, it does not happen especially when I enter this web address there.

kamalmjt commented 4 months ago

To set up Nginx as an SSL reverse proxy for HTTPS offload

Nginx reverse Proxy settings

  location / {
        proxy_pass http://backend_server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

To set up apache as an SSL reverse proxy for HTTPS offload

First need to run command: a2enmod ssl proxy proxy_http headers and add these settings inside virtualhost used for reverse proxy:

Apache reverse proxy settings

ProxyPreserveHost On
ProxyPass / http://backend_server/
ProxyPassReverse / http://backend_server/
RequestHeader set Host %{HTTP_HOST}s
RequestHeader set X-Real-IP %{REMOTE_ADDR}s
RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
RequestHeader set X-Forwarded-Proto %{REQUEST_SCHEME}s

It is not advisable to use Cloudflare with SSL Offload because the data are unencrypted but can change these and try:

But i think laravel does support "cloudflare Flexible - SSL/TLS". Check this: https://community.fly.io/t/laravel-ssl-cloudfare/8618/2 https://stackoverflow.com/questions/42633428/using-cloudflare-flexible-ssl-option-causes-login-form-to-refresh-instead-of-sen

I recoomend to get a Let's Encrypt SSL certificate and put that on your site so that the communication between CloudFlare and your site is all SSL. https://letsencrypt.org/

Bubka commented 4 months ago

I then tried using a reverse proxy (Cloudflared in my case(claudfared creates a claudfare tunnel through which the data is sent and cloudfare then takes care of the certificates, so I don't have to keep renewing them) ) and realised that I was getting a "mixed content" warning and my browser was refusing to load the page.

Hi,

From this point you should have set TRUSTED_PROXIES=*. As cloudflare probably terminates TLS / SSL certificates, it tells 2FAuth to accept http from the proxy while https is expected via APP_URL=https://... This is why your browser complained about mixed content.

Also, if you run v5.0.4 or higher, do not set ASSET_URL, APP_URL is enough.