README.md 6.59 KB
Newer Older
ale's avatar
ale committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
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

18 19 20
The *sso-server* daemon requires a YAML configuration file,
*/etc/sso/server.yml* by default. It understands the following
attributes:
ale's avatar
ale committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

* `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
56
* `keystore`: configures the connection to the keystore service
57
  * `url`: URL for the keystore service
58 59
  * `sharded`: if true, requests to the keystore service will be
    partitioned according to the user's *shard* attribute
60 61 62 63
  * `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
64 65
* `keystore_enable_groups`: (a list) if set, the keystore will only be
  enabled for users that are members of these groups
66 67 68 69
* `u2f_app_id`: set the U2F AppID - if unset, it will be autodetected
  based on the domain name in the request
* `url_path_prefix`: URL path prefix of the SSO server application
  (default /)
70 71 72 73 74 75 76
* `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:
ale's avatar
ale committed
77 78 79
      * `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
80 81 82 83
  * `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
84 85
  * `max_inflight_requests`: maximum number of in-flight requests to
    allow before server-side throttling kicks in
ale's avatar
ale committed
86 87 88 89 90 91 92 93 94 95 96

## 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.

97 98 99 100 101 102 103
## 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.

ale's avatar
ale committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

# 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

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.
128

129 130 131 132 133 134
The new ticket will not be valid any longer than the original one, or
the configured TTL for the new service, whichever comes first.

Group membership in the original ticket is passed along unchanged to
the new ticket.

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

# Implementation notes

The single-sign-on functionality works using HTTP cookies and
redirects between the protected service and the SSO server implemented
in this package. This part works without any Javascript, it's just
plain old HTTP (the browser must accept cookies though). SSO cookies
have a builtin (signed) expiration timestamp, and are set to be
automatically deleted on browser exit.

Logout, on the other hand, is more complex: in order to get the
browser to delete the cookies from the signed-in services, we use
XMLHttpRequests from the logout page, and expect the service logout
endpoints to support authenticated CORS. If Javascript is not
available, however, we try to clear the cookies using image requests,
but this may not work depending on the browser (Safari), or the
presence of privacy-protecting extensions meant to block third-party
cookies. In this case a message is displayed asking the user to quit
the browser, but this isn't really a satisfying solution.