How to configure Signing Workflow

This document describes how to configure PhenixID Signing Workflow.

PhenixID Signing Workflow, and PhenixID Signing Services, (running on Linux) can also be configured using Ansible Automation tool. Please view https://bitbucket.org/phenixidentity/ansible-signing-workflow for more information.

Audience

System administrators.

Prerequisites

- PhenixID Signing Workflow installed

- Workflow database created

Setup PhenixID Signing Services

PhenixID Signing Workflow is dependant on PhenixID Signing Services.

  1. Setup PhenixID Signing Services PDF API using this guide.
    1. Please note that PhenixID Signing Services should be installed on a separate server with own DNS-name etc.
    2. Fetch these values from the PhenixID Signing Services setup:
      1. API username and password
      2. The Files service endpoint URL (if you haven't changed the default values, the endpoint value will be https://<phenixid_signing_services>/files/integration_dev )
      3. The web app endpoint URL (if you haven't changed the default values, the endpoint value will be https://<phenixid_signing_services>/files/pdf_sign )

Configure Signing Workflow

  1. Download config.json.sample from files.phenixid.se
  2. Place the file in the signingworkflow/config folder
  3. Rename the file to config.json

A complete reference guide, describing all configuration parameters in the config.json file, can be found here.

Server Logging

Server logging is controlled by the file config/log4j.xml. If this is a completely new installation the file config/log4j2_template.xml should first be copied to config/log4j2.xml.

The config/log4j2_template.xml contains a typical setup that should work as is. For extended configuration of log4j2 please see the documentation

Web server and SSL termination

  1. Open config.json in a text editor
  2. Change the publicUrl parameter to the name of the server. Example
    "publicUrl": "https://signing-workflow.phenixid.net/",
  3. Save the file.

NB!
The Signing Workflow application server binds to port 8080 (can be changed by config parameter).
SSL termination should be performed by external component, such as load balancer or reverse proxy. The load balancer / reverse proxy should proxy all the traffic to the backend Signing Workflow application server (on port 8080 by default).

 

4. White list the publicURL domain as an allowedLogoutTarget on the PhenixID Signing Services config using this guide.

SQL database connection

  1. Open config.json in a text editor
  2. Change the database parameters in the database section:
    1. url = the jdbc url string. Format: "jdbc:<sql_driver_type>://<database_ip>:<database_port>;database=workflow". Please consult JDBC documentation for details.
    2. driver_class = the sql driver java class.  Please consult JDBC documentation for details.
    3. user = the database user userID value.
    4. password = the database user password value.

In the example below, the MS SQL database named workflow is located on a database server with the ip address 10.128.22.34 on port 61466. The database user workflow_owner with password Secret8899 is used by Signing Workflow to connect to the database. The connection is also set to not validate TLS certificates (trustServerCertificate=true).

 "database": {
    "url": "jdbc:sqlserver://10.128.22.34:61466;database=workflow;trustServerCertificate=true",
    "driver_class": "com.microsoft.sqlserver.jdbc.SQLServerDriver",
    "user": "workflow_owner",
    "password": "Secret8899",
    "maxPoolSize": "3",
    "changelog": "db_migrations/changelog.master.xml",
    "migrations_enabled": true
  }

3. Save the file

4. Start the PhenixID Signing Workflow service.

5. Check logs/server.log for database-related issues/errors.
(Other, subsequent errors can be ignored).

6. If no database-related issues/errors were found, connect to the database server and verify that new tables have been created in the workflow database.

Create temporary PDF file storage

PDF documents which are part of an ongoing workflow are stored in a folder on disk. Follow these steps to create such a folder. Please adjust to suite your needs.

  1. Create a folder in the Signing Workflow root folder called files.
  2. Open config.json in a text editor.
  3. Point to the newly created folder by setting the fileDirectory parameter. This value can be relative (from the Signing Workflow root folder) or absolute.
  4. Save config.json.

Example:

"fileDirectory": "files",

Add token signing certificate

The Signing Workflow application will sign tokens:

- The JWT token for the Signing Services integration (Signing Workflow is the API client)

- The SAML authnRequest for the SAML integration  (Signing Workflow is the SAML SP)

To be able to sign tokens, Signing Workflow needs a key and a corresponding certificate.

 

  1. Create a keypair, CSR and certificate using a tool of your choice (such as OpenSSL, Keystore Explorer, Windows cert mmc)
  2. Export the private key in DER / PKCS8 format (encrypted with a password)
  3. Export the certificate chain in PEM format.
  4. Create a folder in the Signing Workflow root folder, name the folder certs
  5. Add the private key file and the certificate file to the folder.
  6. Open config.json in a text editor.
  7. Change these parameters:
    1. privateKeyFile = Private key file path
    2. publicCertFile = Public cert file path
    3. privateKeyFilePassword = Password to the private key file

Example:

"privateKeyFile": "C:/PhenixID/SigningWorkflow/certs/token_signer.pkcs8",
"publicCertFile": "C:/PhenixID/SigningWorkflow/certs/token_signer.cer",
"privateKeyFilePassword" : "xyxFsgdbee"

8. Save the file.

Add PhenixID Signing Services connection info

  1. Open config.json in a text editor.
  2. Change these parameters:
    1. signingService -> url = Set to previously fetched value (Signing Services web app endpoint URL)
    2. fileService -> url = Set to previously fetched value (Signing Services Files services REST endpoint URL)
    3. fileService -> username = Set to previously fetched value (API username)
    4. fileService -> password =  Set to previously fetched value (API password)

Example:

"signingService": {
    "url": "https://signing.phenixid.net/pdf_sign/"
  },
  "fileService": {
    "url": "https://signing-service.phenixid.net/files/integration_dev",
    "username": "workflow",
    "password": "secret7zce"
  }

3. Save the file.

SAML Federation

Signing Workflow always rely on external authentication and authorization, using a SAML federation. Signing Workflow will always act as a SAML Service Provider, SP, against an external SAML Identity Provider IdP.

Configure Signing Workflow as a SAML Service Provider

  1. Open config.json in a text editor.
  2. Change these parameters:
    1. saml->assertionConsumerServiceUrl = The Assertion Consumer URL (POST) of this SAML SP. Set to <signing_workflow_public_url>/auth/saml
    2. saml->issuerId = The entityID of this SAML SP. Set to <signing_workflow_public_url>/saml/sp

Example:

"saml": {
    "postSsoUrl": "https://idp.phenixid.net/saml/authenticate/idp",
    "assertionConsumerServiceUrl": "https://signing-workflow.phenixid.net/auth/saml",
    "issuerId": "https://signing-workflow.phenixid.net/saml/sp",
    "defaultLocale": "sv",

3. Save the file.

Create Signing Workflow SAML Service Provider metadata

  1. Open a text editor.
  2. Copy the xml template text below and paste it into the text editor.
  3. Replace YOUR_ENTITY_ID with the issuerId value set in previous step
  4. Replace YOUR_ASSERTION_URL with the assertionConsumerServiceUrl value set in previous step
  5. Open the file refered to in jwt->publicCertFile in a text editor
  6. Copy the content, without the PEM tags rows (----BEGIN.... and -----END...)
  7. Replace YOUR_CERTIFICATE with the certificate content copied.
  8. Save the file as signing-workflow-sp-metadata.xml.

 

XML template:

<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="YOUR_ENTITY_ID">
  <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <md:KeyDescriptor use="signing">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:X509Data>
          <ds:X509Certificate>YOUR_CERTIFICATE</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </md:KeyDescriptor>
    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="YOUR_ASSERTION_URL" index="1"/>
  </md:SPSSODescriptor>
</md:EntityDescriptor>

 

Ready XML example:

<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://signing-workflow.phenixid.net/saml/sp">
  <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <md:KeyDescriptor use="signing">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:X509Data>
          <ds:X509Certificate>MIIDnTCCAoWgAwIBAgIQR0Czn5/+qq1LvP4IHzrkcTANBgkqhkiG9w0BAQsFADBVMRIwEAYKCZImiZPyLGQBGRYCc2UxGTAXBgoJkiaJk/IsZAEZFgljYW1iaW9zeXMxEzARBgoJkiaJk/IsZAEZFgNkZXYxDzANBgNVBAMTBmRldi1jYTAeFw0xNjEwMTcxMjQ4MjVaFw0yNjEwMTcxMjU4MjVaMFUxEjAQBgoJkiaJk/IsZAEZFgJzZTEZMBcGCgmSJomT8ixkARkWCWNhbWJpb3N5czETMBEGCgmSJomT8ixkARkWA2RldjEPMA0GA1UEAxMGZGV2LWNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmFuHm/mG/GMMIMHj2RJgFho5jZj9375TBrbKNg0phgPY6wcPR/cvMXMSwbFTs3sjoJAeW7686CnRYH94UPNCrrlgFfDx+aVcYmaIw1wvFeiZEjHV7EYw1CbE2DV0U8TX7I8kNmbalCKJdU46dSRzusyN3ZTMhh7fKmgqkjh+ssgWUWEjuLtKmFLt8AxR/ptRdaP9JVLLvYGfZZwOfSWP6+FS7YXHSCa94uo0uiIPIsY0YEyoqMhNpeiM0TmDIm2Ap0FBjnckyUA1QdfHMTTomHBEj9MdDypaXYu3pAMxLlpTOzSAm8NI6BVIsGT31fNUH8u0KuX4hwnisgvxh/kDIQIDAQABo2kwZzATBgkrBgEEAYI3FAIEBh4EAEMAQTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUKCZF837dqjBCGjNJC99MFpV1+AwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQELBQADggEBAFFvC6WB+JwIATaCUTTN7SdPBfifbLgDG3fYvhh+FV31mmxjl9g8fXy/dp+dcRLePe/FZ5+YW9OCFLbUaCbaeCqh8YGyKpqgxI2EE/cxL4O6lhiK9I4ZjaI4BK7U3wgEr7MvvTTzgJtQDoeESWCwWsBectAwPS4JWPL09xyD1XzbuB8dmYej32Hk3zsCuWGzA03xqdw90HpLTGRr/BQm44+6NrMsUwyYcMMtfkIRNTHCiIv2XcZxvGfPq4pywf+bY1GcFi69C4q80L9pwrbTA6/R0R5p8ZoO5cED8xD6FCGc30waxAsdJ8fC5kd/BXpX0ybuLnCEd5bTvahD10V8ASs=</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </md:KeyDescriptor>
    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://signing-workflow.phenixid.net/auth/saml" index="1"/>
  </md:SPSSODescriptor>
</md:EntityDescriptor>

SAML attribute mapping

NameID

The NameID value from the IdP must be populated with:

- A unique identifier for internal users (=users residing in customer directory(ies), such as sAMAccountName, userPrincipalName, uid (depending on the user store etc)

- A unique identifier for external users (=users not residing in customer directory(ies), such as social security number

Attributes
  1. Open config.json in a text editor.
  2. Locate and change these parameters if needed:
    1. saml->attributes->authority = Name of the attribute containing a value defining the Signing Workflow role of the user. Signing workflow has one role which is called solicitor. Users with the solicitor role will be able to create new signing workflow errands. This saml attribute must contain the string "role:solicitor" (or the configured roles->solicitor value) if the user is a solicitor.
      (If the user is not a solicitor, the user will be able to login and see the workflow errands where the user is a requested signer).
    2. saml->attributes->source = Name of the attribute containing the source value of the user. The attribute value must be set to INTERNAL (for internal users) or EXTERNAL (for external users)
    3. saml->attributes->firstName = Name of the attribute containing the given name value of the user. The given name value is only used for display purposes.
    4. saml->attributes->lastName = Name of the attribute containing the surname value of the user. The surname value is only used for display purposes.
    5. saml->attributes->mail = Name of the attribute containing the mail value of the user. The mail value is used for email notifications.

Example:

"saml": {
  .
  .
  .
  .
    "attributes": {
      "authority": "role",
      "source": "source",
      "firstName": "givenName",
      "lastName": "sn",
      "mail": "mail"
    },

Distribute info to the SAML Identity Provider administrator

Distribute this info to the SAML Identity Provider administrator to establish trust:

  • signing-workflow-sp-metadata.xml
  • NameID value expected (according to the instruction above)
  • Attribute set (names and expected values according to instruction above

 

Establish trust to SAML Identity Provider

  1. Fetch the SAML Identity Provider metadata (ask IdP admin if unknown)
  2. Open the SAML Identity Provider metadata in a text editor
  3. Fetch these values:
    1. entityID
    2. SingleSignOnService->Binding=HTTP-Post->Location
    3. Signing certificate info.

Example:

4. Set the fetched entityID value in saml->trustedIssuers
5. Set the fetched SingleSignOnService->Binding=HTTP-Post->Location in saml->postSsoUrl
6. Open a text editor and create an empty file
7. Add this text as first line:
-----BEGIN CERTIFICATE-----
8. Add this text as second line:
-----END CERTIFICATE-----
9. Add a line between the first and second line and paste the fetched Signing certificate info.
10. Save the file and name it samltrust.pem.
11. Set saml->trustedCertificates to the filepath of samltrust.pem
12. Save config.json

 

Example:

"saml": {
    "postSsoUrl": "https://demo.phenixid.net/saml/authenticate/democ",
    .
    .
    .
    .
    "trustedIssuers": [
      "https://demo.phenixid.net/saml/idp/democ"
    ],
    "trustedCertificates": [
      "C:/PhenixID/Certs/samltrust.pem"
    ],
    .
  },

SMTP

An optional feature of Signing Workflow is email notifications, sent to signers and solicitors. The email contains information about the signing errand and a link to the errand. No sensitive data is added to the email.

  1. Open config.json
  2. Set these parameters:
    1. smtp->fromAddress = The email from address
    2. smtp->enabled = Enable SMTP true/false (string)
    3. smtp.client->hostname = SMTP hostname or IP
    4. smtp.client->port = SMTP communication port
    5. smtp.client->username = SMTP username.
    6. smtp.client->password = SMTP password.

Save config.json.

The configuration for the client can be extended with any of the available attributes from the Vert.x MailConfig options.

Example:

"smtp": {
    "fromAddress": "[email protected]",
    "enabled": "true",
    "client": {
      "hostname": "<hostname>",
      "port": 25,
      "starttls": "DISABLED",
      "login": "REQUIRED",
      "username": "<user>",
      "password": "<password>"
    }
  },

 

To change email look and texts, please follow the instruction here.

PhenixID Signing workflow includes person search functionality. The purpose is to find the users who should sign the document in the signing workflow errand. User search is divided into three functions, all mandatory:

  • Search internal users - get a list of internal users to choose from matching a specific search filter.
  • Lookup internal user - lookup a specific internal user.
  • Lookup external user - lookup a specific external user.

Signing Workflow calls out to external PhenixID Authentication Services (=Signing Services) over http. PAS performs the search against configured user store(s) and returns a result which Signing Workflow will parse and present / use.

Add endpoints and attribute mappings

  1. Configure PhenixID Signing Services (or Authentication Services) with the Person search API.
  2. Open config.json in a texteditor
  3. Change these parameters:
    1. users->externalUserLookup = The URL of the Person search API method for external user lookup
    2. users->internalUserLookup = The URL of the Person search API method for internal user lookup
    3. users->internalUserSearch = The URL of the Person search API method for internal user search
    4. users->internalUserAttributes->organization = The API method response parameter key name representing the organization
    5. users->internalUserAttributes->userId = The API method response parameter key name representing the userId (should match with the NameID population for internal users)
    6. users->internalUserAttributes->mail = The API method response parameter key name representing the email address
    7. users->internalUserAttributes->firstName = The API method response parameter key name representing the given name of the user
    8. users->internalUserAttributes->lastName = The API method response parameter key name representing the surname of the user
    9. users->internalUserAttributes->mobile = The API method response parameter key name representing the mobile telephone number for the user
    10. users->internalUserAttributes->department = The API method response parameter key name representing the department of the user
    11. users->externalUserAttributes->info = The API method response parameter key name representing info about the external user
    12. users->externalUserAttributes->mail = The API method response parameter key name representing the external user email address
    13. users->externalUserAttributes->mobile = The API method response parameter key name representing the external user mobile phone number
    14. users->externalUserAttributes->firstName = The API method response parameter key name representing the given name of the external user
    15. users->externalUserAttributes->lastName = The API method response parameter key name representing the surname of the external user

Example:

 "users": {
    .
    .
    .
    . 
    "externalUserLookup": "https://signing-service.net:7443/pipes/users/external",
    "internalUserLookup": "https://signing-service.net:7443/pipes/users/internal",
    "internalUserSearch": "https://signing-service.net:7443/pipes/users/search",
    "internalUserAttributes": {
      "organization": "company",
      "userId": "sAMAccountName",
      "mail": "mail",
      "firstName": "givenName",
      "lastName": "sn",
      "mobile": "telephoneNumber",
      "department": "department"
    },
    "externalUserAttributes": {
      "info": "city",
      "mail": "mail",
	  "mobile": "city",
      "firstName": "preferredGivenName",
      "lastName": "sn"
    }
  },
  }

4. Save config.json

5. Restart the PhenixID Signing Workflow service.

Test

  1. Browse to the PhenixID Signing Workflow url
  2. You should be redirected to the IdP
  3. Authenticate
  4. You should be redirected to Signing Workflow and be logged-in
  5. Create signing errand (if you cant find that option you miss the correct role)
  6. Assign one internal and one external signer to the errand.
  7. Once created, verify that both users received a notification and is able to log in and see the errand.
  8. The respective user should now sign the doc, verify that it works like expected
  9. When both users signed, verify that you can download the result (the doc with two signatures)