IRMA-SAML bridge enabling IRMA as a Service via the Signicat Identity Broker. It acts as a SAML Identity Provider, giving access to IRMA credentials as SAML attributes.
You require docker
to be installed, including docker-compose
. This setup was tested on Ubuntu 20.04 LTS.
$ sudo apt install docker.io docker-compose
Firstly run ngrok
or similar such that the IRMA instance to use is accessible from the internet.
This step is unnecessary if you use a pre-existing IRMA instance, or if your development machine is accessible by your phone from the local network.
$ ngrok http 8081
Copy the HTTPS url (for example: https://9dac70c8cabf.ngrok.io) into config.test.json
(see example below) and set the URL in the Docker Compose configuration for the IRMA instance as --url=https://9dac70c8cabf.ngrok.io
.
{
"issuerName": "sidn-irma-saml-bridge",
"host": "localhost:8080",
"postfix": "/irma-saml-bridge",
"jwtPrivateKeyPath": "./dev-keys/jwt.der",
"testIrmaPrivateKeyPath": "./dev-keys/irma-test.der",
"irmaPublicKeyPath": "./dev-keys/irma-test.pub.der",
"samlCertificatePath": "./dev-keys/idp.crt",
"samlPrivateKeyPath": "./dev-keys/idp.der",
"samlMetadataPath": "./dev-keys/metadata",
"httpsUsed": false,
"requestTtlInSec": 900,
"responseTtlInSec": 900,
"defaultMap": {
"host": "9dac70c8cabf.ngrok.io",
"irmaServiceHost": "9dac70c8cabf.ngrok.io",
"postfix": ""
},
"irmaMapping": {
"test": {
"host": "9dac70c8cabf.ngrok.io",
"irmaServiceHost": "9dac70c8cabf.ngrok.io",
"postfix": ""
}
}
}
Now initialize the various crypto keys, build assets and run the project:
$ docker-compose up
By default, docker-compose
caches docker images, so on a second run the previous built images will be used. A fresh build can be enforced using the --build
flag.
$ docker-compose up --build
To run the Docker setup without ngrok
, we need to change three minor things:
- Make the
--url
option of the IRMA server configuration in docker-compose.yml use the URL of your choice (for examplehttp://192.168.0.2:port
) - Update the IRMA server domain in config.test.json to the domain of the
--url
option from your IRMA server configuration (see above). In here, use the port of the IRMA server (8089). The NGINX middleware is not necessary for localhost configurations. Make sure you update all"host"
and"irmaServiceHost"
fields.
We have a bash script for building the sidn-irma-saml-bridge
manually. As prerequisite for this script, you need to install Maven for OpenJDK 17, Node.js and yarn
first.
$ bin/build.sh
After building, the JAR artifact can be found in the ./artifacts/
directory.
You can also check the Dockerfile
for details on how to build and run.
We will now proceed by testing your configuration and setup by integrating with a mock-up SAML Service Provider.
First you need to register this SAML Service Provider, by copying its metadata to the appropriate folder.
curl -o ./dev-keys/metadata/sidn-irma-saml-bridge.xml http://localhost:8080/irma-saml-bridge/test/metadata
Note that you need to restart the project for the configuration change to take hold immediately.
docker-compose down
docker-compose up
You can now visit the test endpoint with your browser. This endpoint initiates the Service Provider so-called Authentication Request to our IRMA SAML bridge Identity Provider. You will be redirected immediately.
Now you should see an IRMA QR code. If not, something is wrong with your setup. Note that you have to enable developer mode in the IRMA app before scanning this QR code will work (as the IRMA instance is not running in Production mode). Scan the QR-code and issue your name.
You should not at any time encounter a (red) error screen during this process.
You will redirected to a page with the following text:
This is a placeholder page to which you have been redirected. No SAML response was verified. It is fine to see this page when testing.
This placeholder page does not test the consumption of the SAML response, only the consumption of a valid SAML Authentication Request. For an end-to-end test, we will now integrate with a public service.
First, you must establish a metadata link between your IdP and the SAMLtest Service Prodiver by using the upload form. Upload the metadata file to this form.
You may need to change the following properties in the metadata file:
- the
entityID
, if it is already registered with SAMLtest. - the
NameIDFormat
tourn:oasis:names:tc:SAML:2.0:nameid-format:transient
, as we use this field not as it was intended for. - the
SingleSignOnService
to use thehttp
(non-HTTPS) path, i.e. http://localhost:8080/irma-saml-bridge/request, as our server can not respond with HTTPS.
Secondly we need to trust the SAMLtest Service Provider by adding their metadata to our folder.
curl -o ./dev-keys/metadata/samltest.xml https://samltest.id/saml/sp
Again, you need to restart the project for the configuration change to take hold immediately.
docker-compose down
docker-compose up
You can now perform the test by going to https://samltest.id/start-idp-test/, and by entering sidn-irma-saml-bridge
or whatever you changed the entityID
to. Again, scan the QR and you will be redirected. It is not possible (anymore) to view the disclosed credentials using this service.
For development you may use any environment you please, but this guide restricts solely to the paid IntelliJ IDEA Ultimate environment.
- Open this project in IntelliJ, wait for the indices to be built, and open Run > Edit Configurations.
- Run 'mvn clean install' to import all dependencies
- Start IrmaSamlBridgeApplication configuration
You now still need to use an IRMA instance to talk to. You can use the IRMA instance as provided by the docker-compose file, but you will need to run your TomEE instance on a different port if you do so. You can change this port in the Server tab under HTTP port. Do not forget to change the host
entry in your configuration file appropriately.
The IRMA SAML bridge can be configured with a file called config.json
in the current working directory. You can also use the environment variable CONFIG_PATH
like -DCONFIG_PATH='./config.json'
to use a path other than the current working directory for this file.
But it also possible to put the application.yaml and config.json in a config directory in the classpath
Note: when not using CONFIG_PATH
you probably need to change the working directory of your Tomcat instance to the directory containing your locally checked out git repository for the IRMA SAML bridge.
In the JSON file add the following key-value pairs:
These keyfiles need to be referred to by the bridge. You can set the following values in this configuration file:
issuerName
: The issuerName for this SAML Identity Provider. When unset/null will use host. This issuerName will be used as EntityID in the SAML session.host
: the default host for this IRMA SAML bridge. Emitted in metadata files, tests etc. May be overridden in specific metadata files if so desired.postfix
: path after the hostname for this IRMA SAML bridge.jwtPrivateKeyPath
: the RSA private key used by this bridge in DER format.testIrmaPrivateKeyPath
: the RSA private key possibly used by this bridge to simulate IRMA go messages in DER format. May be NULL (i.e. in production).irmaPublicKeyPath
: the RSA public key used by IRMA Go in DER format.samlCertificatePath
: the certificate used to sign SAML responses and assertions.samlPrivateKeyPath
: the RSA private key used to sign SAML responses and assertions in DER format.samlMetadataPath
: a folder containing all metadata files.httpsUsed
: should https used for the connection with the IRMA server, default is truerequestTtlInSec
ttl for the request in seconds, default is 360responseTtlInSec
ttl for the request in seconds, default is 360defaultCondiscon
: the default condiscon to use when the client does not provide one. This option is mandatory.defaultMap
: Default IRMA host to use when no SAML issuer was matched in the irmaMapping. You can use{spName}
to provide a dynamic mapping for wildcard hostnames or postfixes.irmaMapping
: a dictionary which specifies for each SAML issuer what IRMA host should be used. Uses the Issuer field in Authnrequests, and uses entityID from the metadata files to make a match.
Such a file will look as follows:
{
"issuerName": null,
"host": "localhost:8080",
"postfix": "/irma-saml-bridge",
"jwtPrivateKeyPath": "./dev-keys/jwt.key",
"testIrmaPrivateKeyPath": "./dev-keys/irma.key",
"irmaPublicKeyPath": "./dev-keys/irma.key.pub",
"samlCertificatePath": "./dev-keys/idp.crt",
"samlPrivateKeyPath": "./dev-keys/idp.key",
"samlMetadataPath": "./dev-keys/metadata",
"httpsUsed": false,
"requestTtlInSec": 900,
"responseTtlInSec": 900,
"defaultCondiscon": [
[
[
"pbdf.gemeente.personalData.fullname"
]
]
],
"defaultMap": {
"host": "{spName}.irma-brug.example.com",
"irmaServiceHost": "irma-brug.example.com",
"postfix": ""
},
"irmaMapping": {
"klant": {
"host": "irma.klant.nl",
"irmaServiceHost": "irma-brug.example.com",
"postfix": "/"
}
}
}
Default location of logging is in the directory /logs. The location can be changed by setting the logging.file.path during startup with JVM parameter -Dlogging.file.path=/whatever/path
To check if the application is UP, goto http://localhost:8080/irma-saml-bridge/actuator/health
{
"status":"UP",
"groups":[
"liveness",
"readiness"
]
}
The health endpoints http://localhost:8080/irma-saml-bridge/actuator/health/liveness or http://localhost:8080/irma-saml-bridge/actuator/health/readiness can be used in tools like Kubernetes
When running the sidn-irma-saml-bridge in production, you are required to generate your own key material analog to the development keys in the dev-keys
directory. The openssl
commands to generate these keys are documented in bin/init.sh
.