# ADFS as SAML IDP for SSO

# Preamble

The EE server and client support the SAML protocol that allows you to configure an external service as IDP (identity provider) for SSO (single sign on). This guide here will explain how to configure Microsoft's ADFS as SAML IDP for SSO. We assume that the ADFS server can firewall / network wise access your server. In addition we assume that your webclient is running on https://example.com, the server is reachable with https://example.com/server (e.g. https://example.com/server/info/ shows you some nice json output). This is your first SAML provider that you want to configure (therefore we give him the ID "1"). ADFS is part of all Windows Server since Windows Server 2003 R2. Screenshots will differentiate based on your actual version. We assume that you already have installed the appropriate role and already have ADFS running as a service.

TIP

This feature is only available in the Enterprise Edition.

# ADFS - Relying Party Trusts

As a first step we have to configure ADFS.

  1. Login to the ADFS server and open the ADFS management console.

  2. Click "Relying Party Trusts"

  3. Click "Add Relying Party Trust"

    from the top right corner of the window. The add wizard appears.

  4. Click Start to begin

    Add Relying Party Trust Wizard

  5. Select data source

    Use the Import File option to import the metadata file.

    Select data source

    Adjust the URL according to your setup. The "1" in the URL is the provider id that we will configure later.

  6. Specify Display Name

    Give it a display name such as Psono and enter any notes you want.

    Specify Display Name

  7. Configure Multi-factor Authentication

    Do not configure multi-factor authentication settings.

    Configure Multi-factor Authentication

  8. Choose Issuance Authorization rules

    Permit all users to access this relying party.

    Choose Issuance Authorization rules

  9. Ready to Add Trust

    Click Next and clear the Open the Claims when this finishes check box.

    Choose Issuance Authorization rules

  10. Finish

    Close this page. The new relying party trust appears in the window.

    Finish

# ADFS - Sending LDAP Attributes

Now lets configure it a little bit more.

  1. Start "Edit Claim Rules" Wizard

    Click "Add Rule" and this will start a claim rule wizard

    Finish

  2. Choose Rule Type

    Select "Send LDAP Attribute as Claims"

    Choose Rule Type

  3. Configure Claim Rule

    Set rules based on the following details:

    Choose Rule Type

# ADFS - Incoming Claim

  1. Start "Edit Claim Rules" Wizard

    Click a second time the "Add Rule" and this will start a claim rule wizard

    Finish

  2. Choose Rule Type

    Add another rule with the rule type "Transform an Incoming Claim"

    Choose Rule Type

  3. Configure Claim Rule

    Set a Persistent identifier for the Name ID based on the following details:

    Choose Rule Type

# ADFS - Authentication Policies

From the ADFS console, click on Authentication Polices, edit Global Primary Authentication … and make sure that Forms Authentication is selected for both Extranet and Intranet

Finish

# ADFS - Export certificate

From the ADFS console, click on Services, the click on certificates. Now export Token-singing certificate

Export token signing certificate

As format select "Base-64 encoded X.509 (.CER)"

Select Format

This is the certificate that we have to use later as IDP x509cert.

# Server (settings.yaml)

During the installation of the server you have created a settings.yaml that needs to be adjusted now.

  1. Generate SP certificate

    You will need a certificate for your service provider (SP) later. You can generate one easily with:

    openssl req -new -newkey rsa:2048 -x509 -days 3650 -nodes -sha256 -out sp_x509cert.crt -keyout sp_private_key.key
    

    This will generate a private key (sp_private_key.key) and the public certificate (sp_x509cert.crt).

  2. Change or add SAML configuration in to settings.yaml. Comments inside the config:

    SAML_CONFIGURATIONS:
        1:
            idp:
                entityId: "http://adfs.yourdomainname.com/adfs/services/trust"
                singleLogoutService:
                    binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
                    url: "https://adfs.yourdomainname.com/adfs/ls/?wa=wsignout1.0"
                singleSignOnService:
                    binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
                    url: "https://adfs.yourdomainname.com/adfs/ls/idpinitiatedsignon.aspx"
                x509cert: |
                    -----BEGIN CERTIFICATE-----
                    CERT_FROM_AZURE_APPLICATION
                    -----END CERTIFICATE-----
                groups_attribute: "groups"
                username_attribute: "username"
                email_attribute: "email"
                username_domain: "USER_DOMAIN"
                required_group: []
                is_adfs: true
                honor_multifactors: true
                max_session_lifetime: 43200
            sp:
                NameIDFormat: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
                assertionConsumerService:
                    binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                attributeConsumingService:
                    serviceName: "Psono"
                    serviceDescription: "Psono password manager"
                    requestedAttributes:
                        -
                            attributeValue: []
                            friendlyName: ""
                            isRequired: false
                            name: "username"
                            nameFormat: ""
                privateKey: "SP_PRIVATE_CERTIFICATE"
                singleLogoutService:
                    binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
                x509cert: "SP_X509CERT"
            strict: true
    
    • Replace http://adfs.yourdomainname.com accordingly
    • Change serviceName to match the name of your Relying Trust name
    • Change USER_DOMAIN to match your domain.tld
    • Replace CERT_FROM_AZURE_APPLICATION with the "Certificate (Base64)" from previous Azure configuration. (remove all line breaks)
    • Replace SP_PRIVATE_CERTIFICATE with the content of the previous generated "sp_private_key.key". (remove all line breaks)
    • Replace SP_X509CERT with the content of the previous generated "sp_x509cert.crt". (remove all line breaks)

    Restart the server afterward

  3. Adjust authentication methods

    Make sure that SAML is part of the AUTHENTICATION_METHODS parameter in your settings.yaml e.g.

    AUTHENTICATION_METHODS: ['SAML']
    

    Restart the server afterward

  4. (optional) Debug Mode

    It is helpful in the later debugging to enable debug mode.

    DEBUG: True
    

    WARNING

    Restart the server afterward and don't forget to remove it before going to production.

# Client (config.json)

Now you have to configure your client, so your users can use this configured IDP.

  1. Basic

    Update your config.json similar to the one shown below.

    {
      ...
        "authentication_methods": ["SAML"],
        "saml_provider": [{
          "title": "SAML Login",
          "provider_id": 1,
          "button_name": "Login "
        }]
      ...
    }
    

    The variable authentication_methods restricts the allowed login methods. In the example above only SAML will be allowed and the normal login "hidden". The title and button_name can be adjusted however you like. The provider_id needs to match the one that you used on your server.

  2. (optional) Automatic login

    You may want to "automatically" click on the login button to initiate the login flow. You can accomplish this by modifying the config.json as shown below:

    {
      ...
        "authentication_methods": ["SAML"],
        "auto_login": true,
      ...
    }
    

    WARNING

    This will only work if you have just one provider configured with only one authentication method. Users won't be able to modify the server url nor choose to register or interact with the login form in any other way.