SATOSA
SATOSA is a proxy written in Python which helps for translating between different authentication protocols such as SAML2, OpenID Connect and OAuth2.
We will slowly learn about SATOSA in details in the coming chapters. For now we will learn how to configure one SATOSA instance to work with our example IdP and service provider.
SP ---> SATOSA FRONTEND <--->SATOSA BACKEND <-----> IdP
Setting up SATOSA
$ git clone https://github.com/IdentityPython/satosa.git
$ cd satosa
$ python3 -m venv .venv
$ source .venv/bin/activate
$ python3 -m pip install wheel
$ python3 -m pip install -e .
$ cd example/
$ cp internal_attributes.yaml.example internal_attributes.yaml
$ cp proxy_conf.yaml.example proxy_conf.yaml
$ cp ~/localhost+2.pem ./proxy.crt
$ cp ~/localhost+2.pem ./backend.crt
$ cp ~/localhost+2-key.pem ./backend.key
$ cp ~/localhost+2-key.pem ./proxy.key
Here we are using the same key/certificate for both the proxy frontend and backend.
Update the proxy_conf.yaml
file first.
--- proxy_conf.yaml.example 2023-11-27 12:48:53.272742476 +0100
+++ proxy_conf.yaml 2023-11-21 16:15:21.878249924 +0100
@@ -1,7 +1,7 @@
-BASE: https://example.com
+BASE: https://localhost:8010
COOKIE_STATE_NAME: "SATOSA_STATE"
-CONTEXT_STATE_DELETE: yes
+CONTEXT_STATE_DELETE: false
STATE_ENCRYPTION_KEY: "asdASD123"
cookies_samesite_compat:
@@ -15,8 +15,8 @@
FRONTEND_MODULES:
- "plugins/frontends/saml2_frontend.yaml"
-MICRO_SERVICES:
- - "plugins/microservices/static_attributes.yaml"
+MICRO_SERVICES: []
+# - "plugins/microservices/static_attributes.yaml"
LOGGING:
version: 1
We are mentioning that we will be using port 8010
along with TLS for the example server.
We are also using both SAML frontend and backend. This is mentioned via the
following in the proxy_conf.yaml
file. There can be more than one frontend and
backend.
BACKEND_MODULES:
- "plugins/backends/saml2_backend.yaml"
FRONTEND_MODULES:
- "plugins/frontends/saml2_frontend.yaml"
We need to setup next frontend and backend.
$ cd plugins/backends/
$ cp saml2_backend.yaml.example saml2_backend.yaml
diff -Naur saml2_backend.yaml.example saml2_backend.yaml
--- saml2_backend.yaml.example 2023-11-21 16:06:31.650318811 +0100
+++ saml2_backend.yaml 2023-11-21 16:26:37.869130158 +0100
@@ -1,14 +1,14 @@
module: satosa.backends.saml2.SAMLBackend
name: Saml2
config:
- idp_blacklist_file: /path/to/blacklist.json
+ #idp_blacklist_file: /path/to/blacklist.json
- acr_mapping:
- "": default-LoA
- "https://accounts.google.com": LoA1
+ # acr_mapping:
+ # "": default-LoA
+ # "https://accounts.google.com": LoA1
# disco_srv must be defined if there is more than one IdP in the metadata specified above
- disco_srv: http://disco.example.com
+ #disco_srv: http://disco.example.com
entityid_endpoint: true
mirror_force_authn: no
@@ -80,8 +80,9 @@
text: "http://sp.logo.url/"
width: "100"
height: "100"
- authn_requests_signed: true
- want_response_signed: true
+ authn_requests_signed: false
+ want_response_signed: false
+ want_assertions_or_response_signed: true
allow_unsolicited: true
endpoints:
assertion_consumer_service:
And the same for the frontend:
$ cd ../frontends/
$ cp saml2_frontend.yaml.example saml2_frontend.yaml
And update it with the following configuration.
--- saml2_frontend.yaml.example 2023-11-27 12:41:56.187392054 +0100
+++ saml2_frontend.yaml 2023-11-21 16:20:25.274196172 +0100
@@ -49,8 +49,8 @@
"remd:contactType": "http://refeds.org/metadata/contactType/security",
},
}
- key_file: frontend.key
- cert_file: frontend.crt
+ key_file: proxy.key
+ cert_file: proxy.crt
metadata:
local: [sp.xml]
Next we will have to generate the metadata for the SATOSA proxy and then start the proxy server itself.
$ cd ../..
$ satosa-saml-metadata proxy_conf.yaml proxy.key proxy.crt
$ gunicorn -b 0.0.0.0:8010 satosa.wsgi:app --keyfile proxy.key --certfile proxy.crt
Updating the IdP with proxy's metadata
Now we have to update the IdP with the proxy's metadata as service provider. We can either link or copy the backend.xml
file for this.
$ ln -s ../../../satosa/example/backend.xml
And then updated the idp_conf.py
file.
--- idp_conf.py.example 2023-11-21 14:41:57.200660142 +0100
+++ idp_conf.py 2023-11-21 16:30:32.719075149 +0100
@@ -2,15 +2,13 @@
# -*- coding: utf-8 -*-
import os.path
+from saml2 import BINDING_HTTP_REDIRECT, BINDING_URI
from saml2 import BINDING_HTTP_ARTIFACT
from saml2 import BINDING_HTTP_POST
-from saml2 import BINDING_HTTP_REDIRECT
from saml2 import BINDING_SOAP
-from saml2 import BINDING_URI
from saml2.saml import NAME_FORMAT_URI
-from saml2.saml import NAMEID_FORMAT_PERSISTENT
from saml2.saml import NAMEID_FORMAT_TRANSIENT
-
+from saml2.saml import NAMEID_FORMAT_PERSISTENT
try:
from saml2.sigver import get_xmlsec_binary
@@ -71,6 +69,8 @@
},
"idp": {
"name": "Rolands IdP",
+ "sign_response": True,
+ "sign_assertion": True,
"endpoints": {
"single_sign_on_service": [
("%s/sso/redirect" % BASE, BINDING_HTTP_REDIRECT),
@@ -113,10 +113,10 @@
},
},
"debug": 1,
- "key_file": full_path("pki/mykey.pem"),
- "cert_file": full_path("pki/mycert.pem"),
+ "key_file": full_path("./server.key"),
+ "cert_file": full_path("./server.pem"),
"metadata": {
- "local": [full_path("../sp-wsgi/sp.xml")],
+ "local": [full_path("./backend.xml")],
},
"organization": {
"display_name": "Rolands Identiteter",
We can then start the IdP server on port 8088
.
$ python idp.py idp_conf
Setting up the service provider
To make things easier, feel free to clone the saml-examples repository, and then look at the sp3 directory.
We copied over the frontend.xml
as the metadata from the proxy service, this will be used as IdP's metadata in the Flask based service provider.
--- ../sp2/saml2_backend.yaml 2022-07-21 14:02:10.464265209 +0200
+++ saml2_backend.yaml 2023-11-21 16:32:31.219046414 +0100
@@ -29,7 +29,7 @@
- {contact_type: support, email_address: support@example.com, given_name: Support}
metadata:
- local: [idp.xml]
+ local: [frontend.xml]
entityid: http://localhost:5000/proxy_saml2_backend.xml
accepted_time_diff: 60
We can start the service next.
$ flask run
Then we can login to the server. If you notice the address bar, you can see that we fist went to the SATOSA proxy and then to the IdP server.