
Multipass
Multipass is a remote proxy which can be used to protect web resources and services using user access control. Users are authenticated using a challenge; prove they are the owner of the registered email address by following a login link.
Multipass implements the idea to authenticate users based on something they own instead of something they know. This is better known as the second factor of Two-factor Authentication.
Login links are encoded JSON Web Tokens containing information about the user and their accessible resources. These tokens are used as access tokens with an expiration date and are signed using an on startup generated RSA key pair.
Goal
Protect internet exposed web resources and services with automatic HTTPS (TLS) and provide user friendly authentication.
Motivation
Many private web resources and services end up exposed on the internet, accessible by anyone. Think IP video cameras, Key-value stores, analytic applications and many more. Using Multipass, these web resources and services can be protected using automatic HTTPS (TLS) and access can be granted on an individual basis.
What's here?
Installation
Download the binary from the releases page. If your platform isn't listed please submit a PR.
Build
Building the Multipass command.
-
Get the Caddy web server source code:
$ go get github.com/mholt/caddy
-
Register Multipass as a caddy plugin by adding multipass to the caddy directive:
Open $GOPATH/src/github.com/mholt/caddy/caddyhttp/httpserver/plugin.go
in your favorite editor and make the following changes.
var directives = []string{
...
"expvar",
"multipass", // <- insert this line somewhere before "proxy"
"proxy",
...
}
-
Get the Multipass source code and build the command:
$ go get github.com/namsral/multipass
$ go install github.com/namsral/multipass/cmd/multipass
The next thing is to create a configuration file and run the multipass command.
Configuration
In the following example, the service running on localhost:2016
is proxied and protected to allow only users with handles leeloo@dallas and korben@dallas to access the /fhloston
and /paradise
resources.
example.com {
bind 0.0.0.0
multipass {
resources /fhloston /paradise
handles leeloo@dallas korben@dallas
basepath /multipass
expires 24h
smtp_addr localhost:2525
mail_from "Multipass <no-reply@dallas>"
}
proxy / localhost:2016
log stdout
}
- resources: path of resources to protect. Default: /
- handles: the handles which identify the users. Required
- basepath: path to the log-in and sign-out page. Default: /multipass
- expires: The time duration after which the token expires. Any time duration Go can parse. Default: 24h
- smtp_addr: Mailserver address used for sending login links. Default: localhost:25
- smtp_user: Mailserver username used for authentication.
- smtp_pass: Mailserver password used for authentication.
- mail_from: From address used in email messages sent to users. Required
How it works
Multipass works by sending the user a login link with an embedded access token. When the user follows the login link the access token is stored in the browser session and used to authenticate the user on successive requests. The access token is a JSON web token containing claims specific to Multipass and signed with a RSA key pair.
User flow:
- User visits protected resource
- User is redirected to log-in page and enters a known handle, e.g. email address
- An user access token is sent to user in the form of a login link
- User follows the login link and is granted access the protected resource
JWT
Access tokens are signed JSON Web Tokens with specific claims like user handle and expire date. The tokens are embedded in login links which are sent to user.
RSA key pairs
By default, Multipass uses a random RSA key pair to sign and verify user access tokens. These tokens can be also be used and verified by others using the public key. Made available at [basepath]/pub.cer
when Multipass is running.
Including a signature prevents others from forging access tokens.
Automatic HTTPS
Multipass piggybacks on the Caddy web server which comes with automatic HTTPS using Let's Encrypt and many more features and plugins.
Reverse Proxy
The user handle which was used to authenticate the user is passed down to the protected web services as a HTTP header:
Multipass-Handle: <user handle>
Extending
Exting Multipass by implementing the Handle Service interface.
The current something they own is the users email address and access tokens are sent to this address. But the something they own can also be a mobile number which can receive SMS messages, or a connected device which can receive Push notifications, chat messages and many more.
By implementing the HandleService, shown below, Multipass can be extended to support other handle services which can identify and notify users.
// A HandleService is an interface used by a Multipass instance to register,
// list user handles and notify users about requested access tokens.
// A handle is a unique user identifier, e.g. email address.
type HandleService interface {
// Register returns nil when the given handle is accepted for
// registration with the service.
// The handle is passed on by the Multipass instance and can represent
// an username, email address or even an URI representing a connection to
// a datastore. The latter allows the HandleService to be associated
// with a RDBMS from which to verify listed users.
Register(handle string) error
// Listed returns true when the given handle is listed with the
// service.
Listed(handle string) bool
// Notify returns nil when the given login URL is succesfully
// communicated to the given handle.
Notify(handle, loginurl string) error
// Close closes any open connections.
Close() error
}
Contributing
Contributing is easy:
- Fork this repo
- Checkout a new branch
- Submit a pull-request
Or follow GiHub's guide to using-pull-requests.