Configure a fail over authenticator for Integrated Windows Authentication

This solution document describes how to configure a solution when the primary authentication is failing and the user is redirected to a username and password authenticator.

Please note that this solution document only describes how this can be accomplished. Adjust the configuration to match your environment

This instruction should only be used by a certified PhenixID Server administrator.


Prerequisities

The IWA authenticator (SAMLWindowsSSO) is configured and working

The Username and password authenticator (PostUidAndPasswordSAML) is configured and working

PAS 3.x or later has to be installed

Configuration

Authenticator

Add the parameter errorRedirect to redirect all failed authentications from the IWA authenticator to the Username Password authenticator.

<p>{
        "id": "4781eb6b-a840-4f90-b1e1-8f234bc84898",
        "alias": "iwa",
        "name": "SAMLWindowsSSO",
        "displayName": "IWA",
        "configuration": {
            "pipeID": "f2b899c6-f3b2-4457-8085-2b2f8d5046bf",
            "idpID": "dc528f2b-ca43-4f69-8a57-721a8b5b9551",
            "authProtocol": "Negotiate",
            "errorRedirect": "/saml/authenticate/noiwa"
        }
    }
</p>
Click to copy

Add the parameter sessionValues to the username and password authenticator, to allow the session from the IWA authentication to be fetched.

<p>{
        "id": "8ff489c6-74b5-4540-b1b0-54c3ae73b364",
        "alias": "noiwa",
        "name": "PostUidAndPasswordSAML",
        "displayName": "NoIWA",
        "configuration": {
            "pipeID": "e2258d3d-964f-44a7-b384-7dbbfce7514f",
            "idpID": "dc528f2b-ca43-4f69-8a57-721a8b5b9551",
            "loginTemplate": "loginNoIWA.template",
            "sessionValues": [
                "mySession"
            ]
        }
  }
</p>
Click to copy

Template

The default login template has been modified in order to work with this scenario.


Pipes

The pipe for IWA has to be modified to also add the value of the current session as "mySession", which will be used by the Username and Password authenticator.

<p>[{
        "id": "IWA-PIPE",
        "valves": [{
            "name": "LDAPSearchValve",
            "config": {
                "connection_ref": "53b1fa60-31c2-4f35-9d86-767a73df4e28",
                "base_dn": "DC=company,DC=local",
                "scope": "SUB",
                "size_limit": "0",
                "filter_template": "samAccountName={{request.username}}"
            }
        }, {
            "name": "SessionLoadValve",
            "config": {
                "id": "{{request.session_id}}"
            }
        }, {
            "name": "SessionPropertyReplaceValve",
            "config": {
                "name": "mySession",
                "value": "{{request.session_id}}"
            }
        }, {
            "name": "SessionPersistValve",
            "config": {}
        }, {
            "name": "FlowFailValve",
            "config": {
                "message": "Everything should fail in this scenario"
            }
        }, {
            "name": "AssertionProvider",
            "config": {
                "targetEntityID": "dc528f2b-ca43-4f69-8a57-721a8b5b9551",
                "nameIDAttribute": "sAMAccountName",
                "sourceID": "https://apache.phenixid.se/saml"
            }
        }]
    }
</p>
Click to copy

The Username and password pipe has to be modified to be able to handle all scenarios.

<p>{
        "id": "NOIWA-PIPE",
        "valves": [{
            "name": "InputParameterExistValidatorValve",
            "config": {
                "param_name": "password",
                "skip_if_expr": "request.authenticatedrequest === 'true'"
            }
        }, {
            "name": "LDAPSearchValve",
            "config": {
                "connection_ref": "53b1fa60-31c2-4f35-9d86-767a73df4e28",
                "base_dn": "DC=company,DC=local",
                "scope": "SUB",
                "size_limit": "0",
                "filter_template": "samAccountName={{request.username}}"
            }
        }, {
            "name": "ItemCreateValve",
            "config": {
                "exec_if_expr": "flow.isEmpty()",
                "dest_id": "dummy"
            }
        }, {
            "name": "SessionLoadValve",
            "config": {
                "id": "{{request.session_id}}",
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "SessionPropertyReplaceValve",
            "config": {
                "name": "mySession",
                "value": "{{request.session_id}}",
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "SessionPersistValve",
            "config": {
                "skip_if_expr": "request.get('session_id') === request.get('mySession’)"
            }
        }, {
            "name": "SessionLoadValve",
            "config": {
                "id": "{{request.mySession}}",
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "PropertyAddValve",
            "config": {
                "name": "SAMLRequest",
                "value": "{{session.SAMLRequest}}",
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "PropertyAddValve",
            "config": {
                "name": "RelayState",
                "value": "{{session.RelayState}}",
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "SessionLoadValve",
            "config": {
                "id": "{{request.session_id}}",
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "SessionPropertyReplaceValve",
            "config": {
                "name": "SAMLRequest",
                "value": "{{item.SAMLRequest}}",
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "SessionPropertyReplaceValve",
            "config": {
                "name": "RelayState",
                "value": "{{item.RelayState}}",
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "SessionPersistValve",
            "config": {
                "skip_if_expr": "request.get('session_id') === request.get('mySession')"
            }
        }, {
            "name": "ItemRemoveValve",
            "config": {
                "item_include_expr": "item.getId() === 'dummy'"
            }
        }, {
            "name": "LDAPBindValve",
            "config": {
                "connection_ref": "53b1fa60-31c2-4f35-9d86-767a73df4e28",
                "password_param_name": "password"
            }
        }, {
            "name": "PropertyRemoveValve",
            "config": {
                "name": "SAMLRequest,RelayState"
            }
        }, {
            "name": "AssertionProvider",
            "config": {
                "targetEntityID": "dc528f2b-ca43-4f69-8a57-721a8b5b9551",
                "sourceID": "",
                "nameIDAttribute": "sAMAccountName",
                "additionalAttributes": "sAMAccountName"
            }
        }]
    }
</p>
Click to copy

Testing

1: Browse to the SP protected by this IdP.

2: User is redirected to the IWA Authenticator

3a: User is authenticated by the IWA  Authenticator. 

3b: User is NOT authenticated by the IWA Authenticator.

4b: User is redirected to the Username and Password Authenticator.

5b :User  is authenticated by the Username and Password Authenticator.

6: User is redirected to the SP with a SAML Assertion.