sso
===

Login server (or *identity provider*, IDP) using the
[ai/sso](https://git.autistici.org/ai/sso) protocol (version 5) for
single-sign on and [auth-server](https://git.autistici.org/id/auth) to
authenticate users.

This repository includes a few separate binaries:

* *sso-server* is the login server / IDP
* *saml-server* is a SSO-to-SAML bridge (for third-party software)
* *sso-proxy* is a reverse HTTP proxy that adds single-sign-on access
  controls to backends

# Configuration

The *sso-server* daemon requires a YAML configuration file,
*/etc/sso/server.yml* by default. It understands the following
attributes:

* `secret_key_file`: path to the Ed25519 secret key (should be exactly
64 bytes)
* `public_key_file`: path to the Ed25519 public key (should be exactly
32 bytes)
* `domain`: SSO domain
* `allowed_services`: a list of regular expressions. A request will be
  allowed only if the target SSO services matches one of these
  expressions.
* `allowed_exchanges`: a list of regular expression source /
  destination pairs (dictionaries with `src_regexp` and `dst_regexp`
  attributes). Exchange requests will only be allowed if source and
  destination SSO services both match one of these pairs.
* `service_ttls`: a list of dictionaries used to set time-to-live for
  SSO tickets for specific services. Each dictionary should have the
  following attributes:
  * `regexp`: regular expression that should match the SSO service
  * `ttl`: TTL in seconds
* `auth_session_lifetime`: time-to-live (in seconds) for the
  sso-server user authentication session. When it expires, the user
  will have to login again.
* `session_secrets`: a list of two (or more, as long as the number is
  even) secret keys to use for HTTP cookie-based sessions, in
  *authentication-key*, *encryption-key* pairs. Authentication keys
  can be 32 bytes (SHA128) or 64 bytes (SHA512), encryption keys
  should be 16 (AES-128), 24 (AES-192) or 32 (AES-256) bytes long. For
  key rotation, multiple pairs (old, new) can be specified so that
  sessions are not immediately invalidated.
* `csrf_secret`: a secret key used for CSRF protection
* `auth_service`: the service name to use for the authentication
  request sent to *auth-server* (generally "sso")
* `device_manager`: configuration for the device tracking module:
  * `auth_key`: a long-term key to authenticate HTTP-based cookies
  * `geo_ip_data_files`: GeoIP databases to use (in mmdb format), if
    unset the module will use the default GeoLite2-Country db
* `keystore`: configures the connection to the keystore service
  * `url`: URL for the keystore service
  * `sharded`: if true, requests to the keystore service will be
    partitioned according to the user's *shard* attribute
  * `tls_config`: client TLS configuration
    * `cert`: path to the client certificate
    * `key`: path to the private key
    * `ca`: path to the CA used to validate the server
* `http_server`: specifies standard parameters for the HTTP server
  * `tls`: server-side TLS configuration
    * `cert`: path to the server certificate
    * `key`: path to the server's private key
    * `ca`: path to the CA used to validate clients
    * `acl`: TLS-based access controls, a list of entries with the
      following attributes:
      * `path` is a regular expression to match the request URL path
      * `cn` is a regular expression that must match the CommonName
        part of the subject of the client certificate
  * `trusted_forwarders`: list of trusted IP addresses (reverse
    proxies). If a request comes from here, we will trust the
    X-Forwarded-Proto and X-Real-IP headers when determining the
    client IP address
  * `max_inflight_requests`: maximum number of in-flight requests to
    allow before server-side throttling kicks in

## Device tracking

The idea is to track a small amount of non-personally-identifying data
for each device, and use it to notify users of unexpected
accesses. This information is tracked by the
[user-meta-server](https://git.autistici.org/id/usermetadb).

It is implemented very simply, with a long-term cookie stored in the
browser.

## Key store

On login, the login server can unlock the user's key store
(see [keystore](https://git.autistici.org/id/keystore)). The
associated key will be cleared either on logout, or when the login
session expires.


# API

The *sso-server* binary serves different types of HTTP traffic:

* the login/logout interface (user-facing)
* the SSO login endpoint (user-facing)
* the SSO ticket exchange endpoint (service-facing)

The ticket exchange API allows a service (the *source*) to exchange a
valid SSO ticket for itself with a SSO ticket, for the same user,
meant for a third-party service (*destination*). Its endpoint is
located at the URL `/exchange` and it accepts the following query
parameters:

* `cur_tkt`: valid source SSO ticket
* `cur_svc`: source SSO service
* `cur_nonce`: nonce for *cur_tkt*
* `new_svc`: destination SSO service
* `new_nonce`: nonce for the new SSO ticket
* `new_groups` (optional): a comma-separated list of groups that the
  destination service might check membership for

Note that annoyingly *cur_svc* and *cur_nonce* are redundant, as they
are already contained within *cur_tkt*, but the SSO ticket API won't
allow us to decode the ticket without verifying it at the same time.