Table of Contents

Seamless upgrade

Note

In an environment where you already have configured an SAML2 IDP or an OIDC OP using the old authentication architecture, it can be really hard to move all existing SPs and RPs to new IDPs and OPs since that would require exchanging new metadata and/or discovery URLs to the remote SP/RP. This is what we will solve here using rewrite rules.

SAML2 IDP

Problem 1: 1-to-1 IDP transition (re-using the same EntityID)

  • You have an existing IDP configured in PAS using the old authentication architecture
  • This IDP is being used by multiple external SPs which you don't have any control over
  • You want to setup a new IDP using the new authentication architecture, and let the existing SPs use the new IDP:
    • Without transferring new metadata to the external SPs
    • Without having to reconfigure the external SPs to use the new meta data URL for the IDP

Example

  • Old IDP:
    • Entity Id: old-uidpwd-entity-id
    • SSO URL: https://127.0.0.1:8443/saml/authenticate/old-uidpwd-idp-id
    • Meta data URL: https://127.0.0.1:8443/saml/authenticate/old-uidpwd-idp-id/?getIDPMeta
  • New IDP:
    • Entity Id: old-uidpwd-entity-id
      • It's the same entity id as the old IDP
      • It's also using the same keystore as the old IDP
    • SSO URL: https://127.0.0.1:8443/authentication/saml/old-uidpwd-entity-id/login
    • Meta data URL: https://127.0.0.1:8443/authentication/saml/old-uidpwd-entity-id/meta
  • We want to redirect all incoming SAML Authn requests for the old IDP to the new IDP, if the request originates from the SP with entity id "external-sp"
    • This will allow selectively moving certain SPs from the old IDP to the new IDP in batches, instead of having to move all at once.

Application router configuration

{
    "id": "my-custom-router",
    "routerId": "applicationRouter",
    "conditionExecutorPoolSize": "10",
    "rewriteRules": [
        {
            "matchPathPattern": "/saml/authenticate/old-uidpwd-idp-id/",
            "replacePathPattern": "/authentication/saml/old-uidpwd-entity-id/meta",
            "matchPathPatternIsRegex": "false",
            "replacePathPatternIsRegex": "false",
            "expressionCondition": "request.getParameter('getIDPMeta') !== null",
            "parseBody": "false"
        },
        {
            "matchPathPattern": "/saml/authenticate/old-uidpwd-idp-id",
            "replacePathPattern": "/authentication/saml/old-uidpwd-entity-id/login",
            "matchPathPatternIsRegex": "false",
            "replacePathPatternIsRegex": "false",
            "expressionCondition": "spId === 'external-sp'",
            "parseBody": "true"
        }
    ]
}

In the snippet above, there are two rewrite rules:

  • The first one will match requests for the meta data for the old IDP - the request will be rewritten to the path for the new IDP's metadata
  • The second one will match requests for the old IDP's regular "login path", for Authn requests from the SP with entity id external-sp
    • The SAML endpoint in the new authentication architecture will determine that the URL has been rewritten, and will then perform a redirect (either using HTTP 302 or automatic form post, depending on how the Authn request was initiated) to the correct URL

Problem 2: Many-to-1 IDP transition (using EntityID-Alias)

  • You have several existing IDPs configured in PAS using the old authentication architecture, but want to move to using a single IDP
  • This IDP is being used by multiple external SPs which you don't have any control over
  • You want to setup a new IDP using the new authentication architecture, and let the existing SPs use the new IDP:
    • Without transferring new metadata to the external SPs
    • Without having to reconfigure the external SPs to use the new meta data URL for the IDP

Example

  • Old IDPs:
    • Entity Id: anything
    • SSO URL: https://127.0.0.1:8443/saml/authenticate/some-id
    • Meta data URL: https://127.0.0.1:8443/saml/authenticate/some-id/?getIDPMeta
  • New IDP:
    • Entity Id: new-uidpwd-entity-id
    • SSO URL: https://127.0.0.1:8443/authentication/saml/old-uidpwd-entity-id/login
    • Meta data URL: https://127.0.0.1:8443/authentication/saml/old-uidpwd-entity-id/meta
  • We want to redirect all incoming SAML Authn requests for the old IDPs to the new IDP, and make sure that we use an entity ID and keystore that the SP recognizes

Example IDP configuration

{
    "assertionProfiles" : [ {
      "id" : "old-idp-id-1",
      "additionalAttributes" : [{
              "name": "urn:oid:2.5.4.42",
              "friendlyName": "givenName",
              "itemAttribute": "givenName"
      }],
      "signResponse" : "true",
      "signAssertion" : "true",
      "encryptAssertion" : "false",
      "keystore" : "some-keystore-id"
    }, {
        "id" : "old-idp-id-2",
        "signResponse" : "false",
        "signAssertion" : "true",
        "encryptAssertion" : "false",
        "keystore" : "some-other-keystore-id"
    }, {
        "id" : "default",
        "signResponse" : "true",
        "signAssertion" : "true",
        "encryptAssertion" : "false",
        "use_if_expr": "true"
    }  ],
    "id" : "my_internal_idp_id",
    "name" : "Saml IDP",
    "keystore" : "5f615cf9-7868-4c73-87e4-f0cceea45ac9",
    "entityID" : "https://mydomain.com/authentication/saml/my_internal_idp_id",
    "entityIDAliases": ["old-idp-id-1", "old-idp-id-2"],
    "requireSigned" : "false",
    "authenticatorId" : "my-authenticator-alias",
    "postSSOURL" : "https://mydomain.com/authentication/saml/my_internal_idp_id/login",
    "redirectSSOURL" : "https://mydomain.com/authentication/saml/my_internal_idp_id/login",
    "postSLOURL" : "https://mydomain.com/authentication/saml/my_internal_idp_id/logout",
    "redirectSLOURL" : "https://mydomain.com/authentication/saml/my_internal_idp_id/logout",
    "strictValidation" : "false",
    "allowUnsolicited" : "true",
    "sendSAMLResponseOnError" : "true",
    "clock_skew_minutes" : "5",
    "allowSSO" : "true",
    "created" : "2024-06-12T09:16:53.489Z",
    "modified" : "2024-09-05T07:02:12.164Z"
}

Note that the allowed Entity ID Aliases need to be configured, and you may also include assertion profiles that the SPs might expect.

Application router configuration

{
    "id": "my-custom-router",
    "routerId": "applicationRouter",
    "conditionExecutorPoolSize": "10",
    "rewriteRules": [
        {
            "matchPathPattern": "/saml/authenticate/old-idp-id-1/",
            "replacePathPattern": "/authentication/saml/new-uidpwd-entity-id/meta",
            "matchPathPatternIsRegex": "false",
            "replacePathPatternIsRegex": "false",
            "expressionCondition": "request.getParameter('getIDPMeta') !== null",
            "parseBody": "false"
        },
        {
            "matchPathPattern": "/saml/authenticate/old-idp-id-1",
            "replacePathPattern": "/authentication/saml/new-uidpwd-entity-id/login",
            "matchPathPatternIsRegex": "false",
            "replacePathPatternIsRegex": "false",
            "expressionCondition": "true",
            "parseBody": "false",
            "useEntityIDAlias": "old-idp-id-1",
            "useAssertionProfile": "old-idp-id-1"
        },
        {
            //same as above for each idp you wish to replace, put in the entityID alias and assertion profile to use. 
        }
    ]
}

In the snippet above, there are two rewrite rules:

  • The first one will match requests for the meta data for the old IDP - the request will be rewritten to the path for the new IDP's metadata
  • The second one will match requests for the old IDP's regular "login path"
    • The SAML endpoint in the new authentication architecture will determine that the URL has been rewritten, and will then perform a redirect (either using HTTP 302 or automatic form post, depending on how the Authn request was initiated) to the correct URL
    • The second one will also include some internal redirect attributes that will be used by the SAML endpoint
      • useEntityIDAlias will make sure that the configured Entity ID Alias is used (make sure it is configured as supported at the IDP config)
      • useAssertionProfile will make sure that the configured Assertion Profile is used. Make sure that the keystore used in the profile is the same as the old IDP.

IDP configuration (strict validation)

In case strict validation of the destination URL is enabled for the IDP ("strictValidation": "true" for the IDP in the SAMLIDP section), the incoming Authn request will fail the validation since it was originally intended for the old IDP's URL. This can be solved by whitelisting the old IDP URL on the new IDP:

    "whiteListDestinationUrls": [
        "https://127.0.0.1:8443/saml/authenticate/old-uidpwd-idp-id"
    ]

Now, the new IDP will approve an Authn request intended for the old IDP's URL.

OIDC OP

Problem

  • You have an existing OIDC OP configured in PAS using the old authentication architecture

  • This OP is being used by multiple external RPs which you don't have any control over

  • You want to setup a new OP using the new authentication architecture, and the let existing RPs use the new OP:

    • Without having to reconfigure the external RPs to use the new discovery URL for the OP

Example

  • Old OP:

    • Discovery URL: https://127.0.0.1:8443/old-tenant/.well-known/openid-configuration
  • New OP:

    • Discovery URL: https://127.0.0.1:8443/new-tenant/.well-known/openid-configuration

Application router configuration

{
    "id": "my-custom-router",
    "routerId": "applicationRouter",
    "conditionExecutorPoolSize": "10",
    "rewriteRules": [
        {
            "matchPathPattern": "/old-tenant/.well-known/openid-configuration",
            "replacePathPattern": "/new-tenant/.well-known/openid-configuration",
            "matchPathPatternIsRegex": "false",
            "replacePathPatternIsRegex": "false",
            "parseBody": "false"
        }
    ]
}

In the snippet above, there is one rewrite rule:

  • It will match the old OP's discovery URL, and then rewrite it into the new OP's discovery URL