Skip to content

Commit

Permalink
auth: Use client-side sessions, more secure authentication.
Browse files Browse the repository at this point in the history
This tracks corresponding changes to the webmail backend in
LBBS commit 3eecedf731fe4e5e411141ea0503477a89dced45.

Accordingly:

* Instead of using server-side sessions, a cookie is used to
  store server connection info, since this is client-driven anyways.
* The password is no longer sent directly to the server for storage.
  Instead, the password is encrypted locally and the encryption key
  is sent to the server, where the server encrypts it into an encrypted
  JWT (JWE) and returns that to the client in a cookie, as well as in
  subsequent HTTP responses. This ensures that neither the server nor
  the client stores the password offline.
* IMAP login is handled explicitly as a separate step during setup,
  rather than being bundled as part of WebSocket setup. This allows
  users to see what authentication protocols are supported before authenticating.
* Currently, only the PLAIN auth method is supported, as before. However,
  in the future challenge/response auth methods could be added, and this would
  allow clients to authenticate to an IMAP server without the webmail server
  ever seeing the plaintext password.
* Because client-side sessions are fixed, the 'Remember Me' functionality,
  which never worked properly previously, now should work.
* All JavaScript is now contained in separate files, which allows the Content
  Security Policy forbidding unsafe inline JavaScript to always be used.
  • Loading branch information
InterLinked1 committed Oct 7, 2023
1 parent 0132ece commit c33cc02
Show file tree
Hide file tree
Showing 9 changed files with 1,377 additions and 724 deletions.
38 changes: 19 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,28 @@ Both are required to make wssmail work. In theory, the components could each hav

No configuration is required of the backend (apart from the WebSocket server port in `net_ws.conf`); as long as you have LBBS running with the appropriate modules loaded, the backend should be good to go. Refer to the [LBBS](https://github.com/InterLinked1/lbbs) repository for more details on that.

The frontend requires the PHP `imap` and `openssl` extensions for SMTP. Please make sure they are enabled.
The frontend requires the PHP `imap` and `openssl` extensions for SMTP. Please make sure they are enabled. The JWT/JWE functionality requires PHP's mbstring extension. You can ensure the PHP and Apache-related (if you are using Apache to reverse proxy) dependencies are satisfied by running the following:

To install the frontend, you will need Composer (for PHPMailer). You can navigate to the directory that will serve the webmail application, then run:
```
wget https://raw.githubusercontent.com/composer/getcomposer.org/main/web/installer -O - -q | php -- --quiet
php composer.phar require phpmailer/phpmailer
apt-get install php-imap php-mbstring
a2enmod rewrite
a2enmod proxy
a2enmod proxy_wstunnel
service apache2 restart
```

Alternately, you can run `php composer.phar install` instead of naming PHPMailer explicitly.

Then, clone or copy the contents of this repository into the above directory.
To install the frontend, you will need Composer. Once you have cloned this repository into the web directory where it will be hosted, run:
```
wget https://raw.githubusercontent.com/composer/getcomposer.org/main/web/installer -O - -q | php -- --quiet
php composer.phar install
```

Alternately, if you already have PHPMailer via Composer on your system, you can specify the path to the autoload file in `config.php`.

Basic configuration of your frontend web server is required for the frontend site. Apart from serving the frontend files, WebSocket connections to your frontend host will also need to be reverse proxied to the LBBS WebSocket server. This could be done as follows, for an Apache HTTP virtualhost:
Basic configuration of your frontend web server is required for the frontend site. There are two ways you can host this application:

* Run the frontend and backend on separate servers. You'll need to specify the WebSocket server info in `config.php`.
* Run the frontend and backend on the same server, and reverse proxy WebSocket connections to the backend. This could be done as follows, for an Apache HTTP virtualhost:

```
RewriteEngine On
Expand All @@ -77,20 +84,13 @@ RewriteRule /(.*) ws://localhost:8143/webmail [P,L]
```

(This assumes that 8143 is your WebSocket port, as configured in LBBS's `net_ws.conf`). Note that this connection is not encrypted, but this is a loopback connection so that does not matter.

The `php-imap` extension is also required, for SMTP functionality. You can ensure the Apache-related dependencies are satisfied by running the following:

```
apt-get install php-imap
a2enmod rewrite
a2enmod proxy
a2enmod proxy_wstunnel
service apache2 restart
```
If you are running the components on different servers, be sure to use TLS for everything.

## Configuring

Configuration of the webmail frontend itself is not required. The client is meant to be readily usable as a generic web-based IMAP and SMTP client right out of the box: it really is plug'n play. However, there are a few things that can be configured, if desired. These are documented in `config.sample.php`. To apply settings, create a `config.php` and put them there.
The client is meant to be readily usable as a generic web-based IMAP and SMTP client right out of the box: it really is plug'n play. However, there are a few things that can be configured, if desired. These are documented in `config.sample.php`. To apply settings, create a `config.php` and put them there.

One thing you will want to consider is the server key, used for encrypting JWTs (JWEs). This is set at the top of `config.php`. Be sure to change the default key to something private to the frontend server!

By default, wssmail may be used with any mail server on demand. If you would like to restrict the webmail client to a particular mail server, for instance (which is typical with many deployed webmail sites, which are coupled to a specific mail server), you can force the server settings:

Expand Down
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"require": {
"phpmailer/phpmailer": "^6.8"
"phpmailer/phpmailer": "^6.8",
"web-token/jwt-encryption": "^3.2",
"web-token/jwt-encryption-algorithm-aescbc": "^3.2",
"web-token/jwt-encryption-algorithm-aeskw": "^3.2"
}
}
108 changes: 107 additions & 1 deletion config.sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,42 @@
* Create a config.php file in this directory, and create your settings there. */

/* Path to composer autoload file. Default is vendor/autoload.php */
/* $settings['login']['composer_autoload_path'] = '../vendor/autoload.php';

# $settings['login']['composer_autoload_path'] = '../vendor/autoload.php';

/* Symmetric key for JWE encryption and decryption. Should be private to the server. See https://web-token.spomky-labs.com/the-components/encrypted-tokens-jwe/jwe-loading
* This must be configured for 'Remember Me' to work. */

# NOTE: YOU MUST CHANGE THIS KEY!
# $settings['jwt']['key'] = 'dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g';

/* Hostname of WebSocket backend. By default, WebSocket connections are made to the same hostname
* from which the website is served, and your backend server can reverse proxy to a different port if needed.
* If the webmail backend (LBBS net_ws and mod_webmail) are running on a different server than your web server,
* you can provide the hostname of the BBS server here. This will cause the WebSocket connection
* to be established to the other server directly.
* Note that IMAP hostnames are relative to the backend WebSocket server, NOT the frontend web server serving PHP.
* For example, "localhost" would refer to the backend server, not the frontend server, since the WebSocket server
* is what establishes the IMAP connection forward, on behalf of the client.
*/

# $settings['websocket']['hostname'] = 'example.com';

/* By default, the WebSocket connection uses HTTP if the website loaded over HTTP
* and uses HTTPS if the website loaded over HTTPS. However, if your webmail server
* is using HTTPS but your webmail backend isn't, or vice versa, you should set the security explicitly.
* WARNING: All connections should use HTTPS if traversing public networks!!!
*/

# $settings['websocket']['https'] = true;

/* WebSocket port. By default, this is port 80 if the website loaded over HTTP
* and port 443 if the website loaded over HTTPS. */

# $settings['websocket']['port'] = 8143;

/* Base WebSocket URI path to use in the connection. Default is '/webmail' */
# $settings['websocket']['uri'] = '/webmail';

/* If set, these settings will force the settings to the provided configuration,
* and they will not be user-configurable.
Expand Down Expand Up @@ -35,4 +70,75 @@
$i++;
*/

$settings['presets'][$i]['name'] = "Office365";
$settings['presets'][$i]['imap']['server'] = 'outlook.office365.com';
$settings['presets'][$i]['imap']['security'] = 'tls';
$settings['presets'][$i]['imap']['port'] = 993;
$settings['presets'][$i]['smtp']['server'] = 'smtp.office365.com';
$settings['presets'][$i]['smtp']['security'] = 'starttls';
$settings['presets'][$i]['smtp']['port'] = 587;
$settings['presets'][$i]['imap']['append'] = true;
$i++;

$settings['presets'][$i]['name'] = "Gmail";
$settings['presets'][$i]['imap']['server'] = 'imap.gmail.com';
$settings['presets'][$i]['imap']['security'] = 'tls';
$settings['presets'][$i]['imap']['port'] = 993;
$settings['presets'][$i]['smtp']['server'] = 'smtp.gmail.com';
$settings['presets'][$i]['smtp']['security'] = 'tls';
$settings['presets'][$i]['smtp']['port'] = 465;
$settings['presets'][$i]['imap']['append'] = true;
$i++;

$settings['presets'][$i]['name'] = "Yahoo";
$settings['presets'][$i]['imap']['server'] = 'imap.mail.yahoo.com';
$settings['presets'][$i]['imap']['security'] = 'tls';
$settings['presets'][$i]['imap']['port'] = 993;
$settings['presets'][$i]['smtp']['server'] = 'smtp.mail.yahoo.com';
$settings['presets'][$i]['smtp']['security'] = 'tls';
$settings['presets'][$i]['smtp']['port'] = 465;
$settings['presets'][$i]['imap']['append'] = true;
$i++;

$settings['presets'][$i]['name'] = "iCloud";
$settings['presets'][$i]['imap']['server'] = 'imap.mail.me.com';
$settings['presets'][$i]['imap']['security'] = 'tls';
$settings['presets'][$i]['imap']['port'] = 993;
$settings['presets'][$i]['smtp']['server'] = 'smtp.mail.me.com';
$settings['presets'][$i]['smtp']['security'] = 'starttls';
$settings['presets'][$i]['smtp']['port'] = 587;
$settings['presets'][$i]['imap']['append'] = true;
$i++;

$settings['presets'][$i]['name'] = "Yandex";
$settings['presets'][$i]['imap']['server'] = 'imap.yandex.com';
$settings['presets'][$i]['imap']['security'] = 'tls';
$settings['presets'][$i]['imap']['port'] = 993;
$settings['presets'][$i]['smtp']['server'] = 'smtp.yandex.com';
$settings['presets'][$i]['smtp']['security'] = 'tls';
$settings['presets'][$i]['smtp']['port'] = 465;
$settings['presets'][$i]['imap']['append'] = true;
$i++;

$settings['presets'][$i]['name'] = "PurelyMail";
$settings['presets'][$i]['imap']['server'] = 'imap.purelymail.com';
$settings['presets'][$i]['imap']['security'] = 'tls';
$settings['presets'][$i]['imap']['port'] = 993;
$settings['presets'][$i]['smtp']['server'] = 'smtp.purelymail.com';
$settings['presets'][$i]['smtp']['security'] = 'tls';
$settings['presets'][$i]['smtp']['port'] = 465;
$settings['presets'][$i]['imap']['append'] = true;
$i++;

$settings['presets'][$i]['name'] = "Riseup";
$settings['presets'][$i]['imap']['server'] = 'mail.riseup.net';
$settings['presets'][$i]['imap']['security'] = 'tls';
$settings['presets'][$i]['imap']['port'] = 993;
$settings['presets'][$i]['smtp']['server'] = 'mail.riseup.net';
$settings['presets'][$i]['smtp']['security'] = 'tls';
$settings['presets'][$i]['smtp']['port'] = 465;
$settings['presets'][$i]['imap']['append'] = true;
$i++;

?>
Loading

0 comments on commit c33cc02

Please sign in to comment.