This document describes how to install and configure the SATOSA proxy.
SATOSA requires Python 3.4 (or above), and the following packages on Ubuntu:
apt-get install libffi-dev libssl-dev xmlsec1
-
Download the SATOSA proxy project as a compressed archive and unpack it to
<satosa_path>
. -
Install the application:
pip install <satosa_path>
Alternatively the application can be installed directly from PyPI (pip install satosa
), or the Docker image can be used.
All default configuration files, as well as an example WSGI application for the proxy, can be found in the example directory.
SATOSA proxy configuration: proxy_conf.yaml.example
Parameter name | Data type | Example value | Description |
---|---|---|---|
BASE |
string | https://proxy.example.com |
base url of the proxy |
COOKIE_STATE_NAME |
string | vopaas_state |
name of cooke VOPaaS uses for preserving state between requests |
STATE_ENCRYPTION_KEY |
string | 52fddd3528a44157 |
key used for encrypting the state cookie, will be overriden by the environment variable SATOSA_STATE_ENCRYPTION_KEY if it is set |
INTERNAL_ATTRIBUTES |
string | example/internal_attributes.yaml |
path to attribute mapping |
PLUGIN_PATH |
string[] | [example/plugins/backends, example/plugins/frontends] |
list of directory paths containing any front-/backend plugins |
BACKEND_MODULES |
string[] | [oidc_backend, saml2_backend] |
list of plugin names to load from the directories in PLUGIN_PATH |
FRONTEND_MODULES |
string[] | [saml2_frontend] |
list of plugin names to load from the directories in PLUGIN_PATH |
MICRO_SERVICES |
string[] | [statistics_segit lorvice.yaml] |
list of plugin names to load from the directories in PLUGIN_PATH |
USER_ID_HASH_SALT |
string | 61a89d2db0b9e1e2 |
salt used when creating the persistent user identifier, will be overriden by the environment variable SATOSA_USER_ID_HASH_SALT if it is set |
CONSENT |
dict | see configuration of Additional Services | optional configuration of consent service |
ACCOUNT_LINKING |
dict | see configuration of Additional Services | optional configuration of account linking service |
LOGGING |
dict | see Python logging.conf | optional configuration of application logging |
Parameter name | Data type | Example value | Description |
---|---|---|---|
enable |
bool | Yes |
whether the service should be used |
rest_uri |
string | https://localhost |
url to the REST endpoint of the service |
redirect |
string | https://localhost/redirect |
url to the endpoint where the user should be redirected for necessary interaction |
endpoint |
string | handle_consent |
name of the endpoint in VOPaas where the response from the service is received |
sign_key |
string | pki/consent.key |
path to key used for signing the requests to the service |
verify_ssl |
bool | No |
whether the HTTPS certificate of the service should be verified when doing requests to it |
If using the CMService for consent management and the ALService for account linking, the redirect
parameter should be https://<host>/consent
and https://<host>/approve
in the respective configuration entry.
Attribute mapping configuration: internal_attributes.yaml
The values directly under the attributes
key are the internal attribute names.
Every internal attribute has a map of profiles, which in turn has a list of
external attributes names which should be mapped to the internal attributes.
If multiple external attributes are specified under a profile, the proxy will store all attribute values from the external attributes as a list in the internal attribute.
Sometimes the external attributes are nested/complex structures. One example is the address claim in OpenID connect which consists of multiple sub-fields, e.g.:
"address": {
"formatted": "100 Universal City Plaza, Hollywood CA 91608, USA",
"street_address": "100 Universal City Plaza",
"locality": "Hollywood",
"region": "CA",
"postal_code": "91608",
"country": "USA",
}
In this case the proxy accepts a dot-separated string denoting which external
attribute to use, e.g. address.formatted
.
Example
attributes:
mail:
openid: [email]
saml: [mail, emailAdress, email]
address:
openid: [address.formatted]
saml: [postaladdress]
This example defines two attributes internal to the proxy, named mail
and address
accessible to any plugins (e.g. front- and backends) in the proxy and their mapping
in two different "profiles", named openid
and saml
respectively.
The mapping between received attributes (proxy backend) <-> internal <-> returned attributes (proxy frontend) is defined as:
- Any plugin using the
openid
profile will use the attribute value fromemail
delivered from the backing provider as the value formail
. - Any plugin using the
saml
profile will use the attribute value frommail
,emailAdress
andemail
depending on which attributes are delivered by the backing provider as the value formail
. - Any plugin using the
openid
profile will use the attribute value under the keyformatted
in theaddress
attribute delivered by the backing provider.
The user identifier generated by the backend module can be overridden by
specifying a list of internal attribute names under the user_id_from_attr
key.
The attribute values of the attributes specified in this list will be
concatenated and hashed to be used as the user identifier.
To store the user identifier in a specific internal attribute, the internal
attribute name can be specified in user_id_to_attr
.
When the ALService is used the
user_id_to_attr
should be used, since that account linking service will
overwrite the user identifier generated by the proxy.
The proxy can hash any attribute value (e.g., for obfuscation) before passing
it on to the client. The hash
key should contain a list of all attribute names
for which the corresponding attribute value should be hashed before being
returned to the client.
The protocol specific communication is handled by different plugins, divided into frontends (receiving requests from clients) and backends (sending requests to backing identity providers).
Common configuration parameters:
Parameter name | Data type | Example value | Description |
---|---|---|---|
organization |
dict | {display_name: Example Identities, name: Example Identities Organization, url: https://www.example.com} |
information about the organization, will be published in the SAML metadata |
contact_person |
dict[] | {contact_type: technical, given_name: Someone Technical, email_address: technical@example.com} |
list of contact information, will be published in the SAML metadata |
key_file |
string | pki/key.pem |
path to private key used for signing(backend)/decrypting(frontend) SAML2 assertions |
cert_file |
string | pki/cert.pem |
path to certificate for the public key associated with the private key in key_file |
metadata["local"] |
string[] | [metadata/entity.xml] |
list of paths to metadata for all service providers (frontend)/identity providers (backend) communicating with the proxy |
attribute_profile |
string | saml |
attribute profile to use for mapping attributes from/to response |
The metadata could be loaded in multiple ways in the table above it's loaded from a static file by using the key "local". It's also possible to load read the metadata from a remote URL.
Examples:
Metadata from local file:
"metadata":
local: [idp.xml]
Metadata from remote URL:
"metadata": {
"remote":
-url:https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral2&set=saml2,
-cert:null
}
For more detailed information on how you could customize the SAML entities configuration please visit: https://dirg.org.umu.se/static/pysaml2/howto/config.html
The SAML2 frontend acts as an SAML Identity Provider (IdP), accepting authentication requests from SAML Service Providers (SP). The default configuration file can be found here.
The SAML2 frontend comes with two different behaviours:
The SamlMirrorFrontend module mirrors the target identity provider information on to the frontend metadata. Because of this the frontend uses a dynamic entity id depending on the target IDP/OP and behaves as several IDPs. The target is chosen by picking the associated frontend IDP. This gives a "direct connection" to the targeted IDP/OP.
The SamlFrontend module acts like a regular IDP and hides the target identity provider. The target is chosen by using a sso endpoint in the frontend IDP associated to a specific backend. It is the backend modules job to pick an identity provider.
The SAML2 frontends can provide an authenication class reference in the AuthnStatement
of the
assertion in the authentication response. This can be used to describe the Level of Assurance,
as described for example by eIDAS.
The AuthnContextClassRef
(ACR) can be specified per backing provider in a mapping under the
configuration parameter acr_mapping
. The mapping must contain a default ACR under the key ""
(empty string), other ACR value specific per provider is specified with key-value pairs, where the
key is the providers id (entity id for SAML IdP behind SAML2 backend, authorization endpoint URL for
OAuth AS behind OAuth backend, and issuer for OpenID Connect OP behind OpenID Connect backend).
If no acr_mapping
is provided in the configuration, the ACR from the backend plugin will
be used instead. This means that when using a SAML2 backend, the ACR provided by the backing
provider will preserved and passed on in the authentication response, and when using a OAuth or
OpenID Connect backend, the ACR will be urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified
.
Example
config:
config: [...]
acr_mapping:
"": default-LoA
"https://accounts.google.com": LoA1
The SAML2 backend acts as an SAML Service Provider (SP), making authentication requests to SAML Identity Providers (IdP). The default configuration file can be found here.
The SAML backend could indicate which name ID formats are supported to adding name_id_format under the SP element in the configuration file. By defining the hash_type attribute in the configuration it's possible to enter a name_id_format in the authentication request sent to the identity provider.
To allow the user to choose which provider they want to use to authenticate with, specify the
configuration parameter disco_srv
, e.g.
config:
config: [...]
disco_srv: http://disco.example.com
The OpenID Connect backend acts as an OpenID Connect Relying Party (RP), making authentication requests to OpenID Connect Provider (OP). The default configuration file can be found here.
Only the op_url
must be configured to specify the OP issuer url.
The example configuration assumes the OP supports discovery and dynamic client registration. When using an OP that only supports statically registered clients, see the default configuration for using Google as the OP.
The social login plugins can be used as backends for the proxy, allowing the proxy to act as a client to the social login services.
The OpenID Connect frontend acts as and OpenID Connect Provider (OP), accepting requests from OpenID Connect Relying Parties (RPs). The default configuration file can be found here.
The configuration parameters available:
signing_key_path
: path to a RSA Private Key file (PKCS#1). MUST be configured.client_db_path
: path to where the client (RP) database will be stored. The other parameters should be left with their default values.
As opposed to the other plugins, this plugin is NOT stateless (due to the client database). This makes it impossible to run multiple instances of the SATOSA proxy on different machines (for the purpose of load balancing) unless the client database file is also distributed among those machines by some external process.
The default configuration file can be found here.
The only parameters necessary to configure is the credentials,
the client_id
and client_secret
, issued by Google. See OAuth 2.0 credentials
for information on how to obtain them.
The redirect_uri
of the SATOSA proxy must be registered with Google. The
redirect URI to register with Google is "<base_url>/google", where <base_url>
is the base url of the proxy as specified in the BASE
configuration parameter
in proxy_conf.yaml
, e.g. "https://proxy.example.com/google".
A list of all claims possibly released by Google can be found here, which should be used when configuring the attribute mapping (see above).
The default configuration file can be found here.
The only parameters necessary to configure is the credentials,
the "App ID" (client_id
) and "App Secret" (client_secret
), issued by Facebook.
See the registration instructions
for information on how to obtain them.
Additional behaviour can be configured in the proxy through "microservices".
To add a set of static attributes, use the AddStaticAttributes
class which will add
pre-configured (static) attributes, see the
example configuration.
The proxy metadata is generated based on the front-/backend plugins listed in proxy_conf.yaml
using the make_satosa_saml_metadata.py
(installed globally by SATOSA installation).
The command
make_satosa_saml_metadata.py proxy_conf.yaml
will generate separate metadata files for all SAML2 backend modules and frontend modules
specified in proxy_conf.yaml
.
Detailed usage instructions can be viewed by running make_satosa_saml_metadata.py -h
.
```bash
usage: make_satosa_saml_metadata.py [-h] [-v VALID] [-c CERT] [-k KEYFILE] [-s]
[-x XMLSEC] [-f] [-b] [-o OUTPUT]
proxy_conf
positional arguments:
proxy_conf path to proxy_conf.yaml
optional arguments:
-h, --help show this help message and exit
-v VALID How long, in days, the metadata is valid from the time of
creation
-c CERT certificate
-k KEYFILE A file with a key to sign the metadata with
-s sign the metadata
-x XMLSEC xmlsec binaries to be used for the signing
-f generate frontend metadata
-b generate backend metadata
-o OUTPUT output path
```
# Start proxy application Start the proxy server with the following command: ```bash gunicorn -b satosa.wsgi:app --keyfile= --certfile= ``` where * `socket address` is the socket address that `gunicorn` should bind to for incoming requests, e.g. `0.0.0.0:8080` * `https key` is the path to the private key to use for HTTPS, e.g. `pki/key.pem` * `https cert` is the path to the certificate to use for HTTPS, e.g. `pki/cert.pem`
This will use the proxy_conf.yaml
file in the working directory. If the proxy_conf.yaml
is
located somewhere else, use the environment variable SATOSA_CONFIG
to specify the path, e.g.:
set SATOSA_CONFIG=/home/user/proxy_conf.yaml