Trusted Central Signing Service - API - Transaction (XML) signing
Prerequisites
- PAS 2.7 or higher installed
- The reader of this document should have some basic knowledge about PhenixID Server.
- Changes will be made to the file phenix-store.json, so please make sure to have a backup of this file.
Add custom CA
Follow this guide to add custom CA to PhenixID Signing Services. This step is recommended to follow to make sure the certificate created before the signing operation is issued by a CA which is trusted in your organisation.
Add module for file upload via API
- Login to PhenixID Authentication Services - Configuration manager
- Click on the tab Advanced
- Click on the pen to the right of Modules
- Append the files module
{
"name": "com.phenixidentity~phenix-files",
"enabled": "true",
"id": "files_01",
"config": {
"read_only": "false",
"name": "integration_dev",
"auth_method": "pipe",
"auth_pipe": "files_auth_01",
"http_configuration_ref": "441b0aad-534e-4cad-8151-130955913c08",
"store_impl": "com.phenixidentity.files.internal.SessionFilesStore"
}
}
NOTE: The values for auth_method can be pipe, basic_auth
- Change the name value to suit your environment. The name value will be part of the url that will receive file uploads. (Example: https://demo.phenixid.net/files/integration_dev)
- Change the http_configuration_ref (reference to HTTP connection) to a value that suits your configuration.
- Click Stage Changes and Commit Changes
- Click on the pen to the right of NODE_GROUPS
- Add the module "files_01" to module_refs.
- Click Stage Changes and Commit Changes
Add pipe for api client authentication (to file upload)
- Logon to Configuration Manager
- Click Advanced
- Click pipes
- Add pipe for authentication of api client.
{
"id": "files_auth_01",
"valves": [
{
"name": "HttpBasicAuthValve",
"enabled": "true",
"config": {
"username_dest": "uid",
"password_dest": "pwd"
}
},
{
"name": "InternalUserStoreValidatorValve",
"enabled": "true",
"config": {
"username": "{{attributes.uid}}",
"password_param_name": "{{attributes.pwd}}"
}
},
{
"name": "ItemCreateValve",
"enabled": "enabled",
"config": {
"dest_id": "{{attributes.uid}}"
}
}
]
}
- Click Stage changes and commit changes
Add api username and password
- Logon to Configuration Manager
- Click Advanced
- Click Internal users
- Copy an object
- Paste object
- Set id (username) and password in object
{
"id": "sign_api_client",
"password": "secret",
"description": "Sign api client caller"
}
- Change the id and password to suite your needs.
- Click Stage changes and Commit changes. The password will be encrypted once the config is saved.
Add prism modules
- Login to configuration manager
- Click Advanced
- Click Modules
Add these modules:
{
"id": "xml_sign_prism_01",
"name": "com.phenixidentity~phenix-prism-fedsigning",
"enabled": "false",
"prism_enabled": "true",
"config": {
"display_name": "PhenixID Signing Service",
"base_uri": "sign",
"sign_auth_redirect_url": "/xml_sign/authenticate/xml_sign_auth_01",
"sign_pipe": "xml_sign_sign_pipe_01",
"http_configuration_ref": "441b0aad-534e-4cad-8151-130955913c08"
}
},
{
"id": "xml_sign_prism_00",
"name": "com.phenixidentity~phenix-prism",
"enabled": "true",
"config": {
"base_url": "/xml_sign",
"auth_redirect_url": "/xml_sign/authenticate/xml_sign_auth_00",
"module_refs": "xml_sign_prism_01",
"http_configuration_ref": "441b0aad-534e-4cad-8151-130955913c08"
}
}
- Change http_configuration_ref to point to a HTTP connection id in your configuration
- Change uri values to suite your needs (ie /xml_sign)
- Click Stage Changes and Commit Changes
- Click on the pen to the right of NODE_GROUPS
- Add the module "xml_sign_prism_00" to module_refs.
- Click Stage Changes and Commit Changes
Add primary authenticator
Add primary authenticator. This authenticator will parse incoming jwt token and add values to the session.
- Login to configuration manager
- Click Advanced
- Click HTTP Authenticator
Add this authenticator:
{
"id": "xml_sign_auth_00",
"alias": "xml_sign_auth_00",
"name": "PipeAuthenticator",
"configuration": {
"pipeID": "xml_sign_pipe_00",
"successURL": "/xml_sign"
}
}
- Click Stage changes and Commit changes
Add pipe
- The integrating party (the application) must create a keypair and certificate to use for JWT signing. Make sure you retrieve the public certificate (.crt) in PEM format. (-----BEGIN CERTIFICATE-----XXX-----END CERTIFICATE-----)
- Create a folder, trusted_certs, in the PhenixID server root folder
- Save the crt file in the folder. In the example below, the filepath is /opt/PhenixID/Server/trusted_certs/api_client.crt.
- Click Advanced
- Click Pipes
Add this pipe:
{
"name": "Xml sign initial auth",
"description": "Pipe for initial auth in xml_sign. Parse jwt token and add properties to session",
"enabled": "true",
"id": "xml_sign_pipe_00",
"valves": [
{
"name": "ItemCreateValve",
"enabled": "true",
"config": {
"dest_id": "_"
}
},
{
"name": "JWTTokenParserValve",
"enabled": "true",
"config": {
"token_parameter": "Authorization",
"additional_attributes": [
"id",
"failURL",
"successURL"
"cancelURL"
],
"certfilepath" : "/opt/PhenixID/Server/trusted_certs/api_client.crt"
}
},
{
"name": "SessionLoadValve",
"enabled": "true",
"config": {
"id": "{{item.jwt_id}}",
"require_session": "true",
"require_auth_session": "false"
}
},
{
"name": "PropertyAddValve",
"enabled": "true",
"config": {
"name": "file_id",
"value": "{{item.jwt_id}}"
}
},
{
"name": "PropertyAddValve",
"enabled": "true",
"config": {
"name": "content",
"value": "{{session.content}}"
}
},
{
"name": "PropertyAddValve",
"enabled": "true",
"config": {
"name": "success_url",
"value": "{{item.jwt_successURL}}"
}
},
{
"name": "PropertyAddValve",
"enabled": "true",
"config": {
"name": "failure_url",
"value": "{{item.jwt_failURL}}"
}
},
{
"name": "PropertyAddValve",
"enabled": "true",
"config": {
"name": "cancel_url",
"value": "{{item.jwt_cancelURL}}"
}
},
{
"name": "PropertyAddValve",
"enabled": "true",
"config": {
"name": "content_type",
"value": "application/xml"
}
} ]
}
Add signature method(s)
First of all, decide which authenticator(s) is to be used from this list of available authenticators for PhenixID web apps authentication.
- Click on the pen to the right of Authentication - HTTP
- Add your authenticator(s) via the step-by-steps described here.
Make sure the successURL is /xml_sign/sign/api/sign.
{
"alias": "xml_sign_auth_01",
"name": "PostUidAndPassword",
"displayName": "Username and password",
"configuration": {
"pipeID": "pipe_xml_sign_auth_01
",
"successURL": "/xml_sign/sign/api/sign"
},
"id": "xml_sign_auth_01"
}
In this example, a simple username and password authenticator is used.
- Click Stage changes and Commit changes
- Click on the pen to the right of Pipes
- Add this pipe configuration. Change connection_ref to the id value fetched in previous step. Change base_dn and filter_template to suit your environment.
{
"id": "pipe_xml_sign_auth_01
",
"valves": [
{
"name": "LDAPSearchValve",
"config": {
"connection_ref": "MyAD",
"base_dn": "DC=demo,DC=phenixid,DC=net",
"scope": "SUB",
"size_limit": "0",
"filter_template": "(&(objectclass=*)(sAMAccountName={{request.username}}))",
"attributes": ""
}
},
{
"name": "LDAPBindValve",
"config": {
"connection_ref": "MyAD",
"password_param_name": "password"
}
},
{
"name": "SessionLoadValve",
"enabled": "true",
"config": {
"id": "{{request.session_id}}"
}
},
{
"name": "SessionPropertyAddValve",
"enabled": "true",
"config": {
"name": "user_id",
"value": "{{request.username}}"
}
},
{
"name": "SessionPersistValve",
"enabled": "true",
"config": {}
}
]
}
- Click Stage changes and Commit changes
Add execution flow (pipe) to sign xml
- Click on the pen to the right of Pipes
- Add this pipe. The configuration in this pipe will fetch the logged-in user attributes from the LDAP store and use these attributes to populate the certificate that will be created in run-time. The certificate will then be used to perform the signing operation of the incoming XML file.
Please note that this might not suit your environment. Valves can be replaced, removed or added based on your needs. Please view the documentation to get a list of available valves.
Change these values to suit your environment:
- LDAPSearchValve: connection_ref, base_dn, filter, attributes
- CreateShortTermKeyStoreValve: subjectKeyParamater, caTemplateKeyParameter (for testing purposes the builtin CA delivered with PhenixID Server can be used. The ID can be found in the file phenix-store.json in the section "CA_CONFIGURATIONS".)
{
"name": "XML sign - Execute Sign",
"description": "Signs xml file stored in supplied session (file_id) and replaces the file with the signed copy.",
"enabled": "true",
"id": "xml_sign_sign_pipe_01",
"valves": [
{
"name": "SessionLoadValve",
"enabled": "true",
"config": {
"id": "{{request.session_id}}"
}
},
{
"name": "LDAPSearchValve",
"config": {
"connection_ref": "MyAD",
"base_dn": "DC=demo,DC=phenixid,DC=net",
"scope": "SUB",
"size_limit": "0",
"filter_template": "sAMAccountName={{session.user_id}}",
"attributes": "givenName,sn,mail"
}
},
{
"name": "PropertyAddValve",
"enabled": "true",
"config": {
"name": "signerID",
"value": "{{session.user_id}}"
}
},
{
"name": "SessionLoadValve",
"enabled": "true",
"config": {
"id": "{{request.file_id}}",
"require_session": "true",
"require_auth_session": "false"
}
},
{
"name": "PropertyAddValve",
"enabled": "true",
"config": {
"name": "content",
"value": "{{session.content}}"
}
},
{
"name": "PropertyBase64DecoderValve",
"config": {
"source": "content",
"dest": "temporary"
}
},
{
"name": "CreateShortTermKeyStoreValve",
"enabled": "true",
"config": {
"subjectKeyParamater": "CN={{item.givenName}} {{item.sn}} ({{item.mail}}),OU=Demo,O=PhenixID",
"caTemplateKeyParamater": "signca",
"keyUsage": [
"true",
"true"
]
}
},
{
"name": "XAdESSignValve",
"enabled": "true",
"config": {
"keyStoreID": "{{item.keyStoreId}}",
"xmlSourceData": "{{item.temporary}}",
"xmlTarget": "document"
}
},
{
"name": "SessionPropertyReplaceValve",
"enabled": "true",
"config": {
"name": "content",
"value": "{{item.document}}"
}
},
{
"name": "SessionPropertyReplaceValve",
"enabled": "true",
"config": {
"name": "modified",
"value": "{{now}}"
}
},
{
"name": "SessionPersistValve",
"enabled": "true",
"config": {}
},
{
"name":"EventValve",
"config":{
"event_key":"EVT_000052",
"parameters":[
{
"parameter":"duser",
"value":"{{item.signerID}}"
},
{
"parameter":"msg",
"value":"Successfully signed"
},
{
"parameter":"phenixIDIdentifier",
"value":"SIGN"
},
{
"parameter":"proto",
"value":"XADES"
}
]
}
}
]
}
- Click Stage changes and Commit changes
Add execution flows (pipe) for verification of signed XML
- Click on the pen to the right of Modules
- Enable http on the pipes module by adding http_enabled=true and http_configuration_ref=<id_of_http_connection> to the configuration.
Example. Make sure you change http_configuration_ref to suite your environment.
{
"name": "com.phenixidentity~phenix-pipes",
"singleton": "true",
"config": {
"http_enabled": "true",
"http_configuration_ref": "441b0aad-534e-4cad-8151-130955913c08"
},
"enabled": "true",
"created": "2017-07-03T11:38:03.057Z",
"id": "01ffd70e-b5fb-4c06-b040-b61760424bf6"
}
- If you enabled http on the pipes module, a restart of PhenixID server must be performed.
- Click on the pen to the right of Pipes
- Add this pipe. The configuration in this pipe will validate the signature to make sure the data has not been altered.
Please note that this might not suit your environment. Valves can be replaced, removed or added based on your needs. Please view the documentation to get a list of available valves. Please also view this document to see how the certificates can be extracted from the signatures (in order to validate the certificates using this valve).
{
"id": "SignAppVerifyPipeAPI_XML",
"description": "Verify signed XML via API ",
"http_enabled": "true",
"http_path_pattern": "PUT:/pipes/verifysign_xml",
"valves": [
{
"name": "ItemCreateValve",
"config": {
"dest_id": "verification_result"
}
},
{
"name": "XAdESVerifyValve",
"enabled": "true",
"config": {
"xmlSourceData": "{{request.body}}"
}
}
]
}
- Click Stage changes and Commit changes
Test
Follow the document found in the chapter Developer integration guide to test your setup.
Troubleshooting
Check server.log file.