Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Configuration of the corporate network for Syndeia SAML2 Authentication further requires that the chosen IdP be configured to recognize Syndeia Cloud as a legitimate SAML2 Service Provider.

Expand
titleA note against IdP-originated SSO

For security reasons and to follow industry best cybersecurity practices, Syndeia Cloud only offers “SP-originated, delegated-to-IdP” authentication. Syndeia Cloud does not support “IdP-initiated, SSO-login”.

See https://www.identityserver.com/articles/the-dangers-of-saml-idp-initiated-sso for a succinct argument against IdP-initiated SSO.

Table of Contents
minLevel2
maxLevel2
outlinetrue

...

  • ssh log into the Syndeia Cloud server with a user that can perform “passwordless sudo” operations. Root access is not necessary, if sudo access has been established.

  • copy all of the following into silhouette.conf, adding or replacing any existing saml2. settings.

  • Replace all EXAMPLE values – like MYSP.COM:SPPORT– with the values for your organization.

Expand
titlesilhouette.conf template
Code Block
languageyaml
  # SAML2 Provider
  # These settings are intentionally similar to what OneLogin needs for SAML2
  # Service Providers and Identity Providers

    # Compression settings. Note that these are determined by OASIS Standard for SAML2
    # false => Base64 encoded, true => Deflated Base64 encoded (which is compressed)
	# saml2.compress.request = true
	# saml2.compress.response = true

    saml2.security.authnrequest_signed = true
    saml2.security.want_messages_signed = true
    saml2.security.want_assertions_signed = true
    saml2.security.want_xml_validation = true
    saml2.security.signature_algorithm = "sha1"
    saml2.security.requested_authncontext = "exact"

    # CAC/PIV authentications might need something like this, which is IdP-specific
    # saml2.security.requested_authncontext = "http://idmanagement.gov/ns/assurance/aal/3?hspd12=true"

    #  Identifier of the SP entity  (must be a URI)
    saml2.sp.entityid = "http://MYSP.COM:SPPORT"

    # Specifies info about where and how the <AuthnResponse> message MUST be
    #  returned to the requester, in this case our SP.
    # URL Location where the <Response> from the IdP will be returned
    saml2.sp.assertion_consumer_service.url = "http://MYSP.com:SPPORT/authenticate/SAML2"

    # SAML protocol binding to be used when returning the <Response>
    # message.  Onelogin Toolkit supports for this endpoint the
    # HTTP-POST binding only
    saml2.sp.assertion_consumer_service.binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"

    # Specifies info about where and how the <Logout Response> message MUST be
    # returned to the requester, in this case our SP.
    saml2.sp.single_logout_service.url = "http://MYSP.com:SPPORT/authenticate/SAML2"

    # SAML protocol binding to be used when returning the <LogoutResponse> or sending the <LogoutRequest>
    # message.  Onelogin Toolkit supports for this endpoint the
    # HTTP-Redirect binding only
    saml2.sp.single_logout_service.binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"

    # Specifies constraints on the name identifier to be used to
    # represent the requested subject.
    # Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported
    saml2.sp.nameidformat = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"

    # Usually x509cert and privateKey of the SP are provided by files placed at
    # the certs folder. But we can also provide them with the following parameters
    saml2.sp.x509cert = "-----BEGIN CERTIFICATE-----BIGLONGSPPUBLICCERTSTRING-----END CERTIFICATE-----"

    # Requires Format PKCS#8   BEGIN PRIVATE KEY
    # If you have     PKCS#1   BEGIN RSA PRIVATE KEY  convert it by   openssl pkcs8 -topk8 -inform pem -nocrypt -in sp.rsa_key -outform pem -out sp.pem
    saml2.sp.privatekey = "-----BEGIN PRIVATE KEY-----BIGLONGSPPRIVATECERTSTRING-----END PRIVATE KEY-----"

    # Identifier of the IdP entity  (must be a URI)
    saml2.idp.entityid = "http://OURIDP.COM:IDPPORT/SAMLIDP"

    # SSO endpoint info of the IdP. (Authentication Request protocol)
    # URL Target of the IdP where the SP will send the Authentication Request Message
    saml2.idp.single_sign_on_service.url = "https://OURIDP.COM:IDPPORT/SSOPATH"

    saml2.idp.single_sign_on_service.binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"

    # Instead of using the whole x509cert you can use a fingerprint in order to
    # validate a SAMLResponse (but you still need the x509cert to validate LogoutRequest and LogoutResponse using the HTTP-Redirect binding).
    # But take in mind that the fingerprint, is a hash, so at the end is open to a collision attack that can end on a signature validation bypass,
    # that why we don't recommend it use for production environments.
    # (openssl x509 -noout -fingerprint -in "idp_crt" to generate it,
    # or add for example the -sha256 , -sha384 or -sha512 parameter)

    # If a fingerprint is provided, then the certFingerprintAlgorithm is required in order to
    # let the toolkit know which Algorithm was used. Possible values: sha1, sha256, sha384 or sha512
    # 'sha1' is the default value.
    #saml2.idp.certfingerprint = "1234"
    #saml2.idp_certfingerprint_algorithm = "sha1"

    saml2.idp.x509cert = "-----BEGIN CERTIFICATE-----BIGLONGIDPPUBLICCERTSTRING-----END CERTIFICATE-----"

    # These are the property keys used to retrieve Social Identity information from the SAML2 Response which an IdP
    # sends back to an SP. The names of the keys are standardized but are configurable here to support internationalization
    # and quirks by IdP vendors like Microsoft
    saml2.social.attribute.key.uid = "uid"
    saml2.social.attribute.key.firstname = "first_name"
    saml2.social.attribute.key.lastname = "last_name"
    saml2.social.attribute.key.fullname = "fullname"
    saml2.social.attribute.key.email = "email"

...

  • ssh log into the Syndeia Cloud server with a user that can perform “passwordless sudo” operations. Root access is not necessary, if sudo access has been established.

  • copy all of the following into application.conf, adding or altering the following Akka Play HTTP settings.

  • Replace all EXAMPLE values – like OURIDP.COM:IDPPORT– with the values for your organization.

Expand
titleapplication.conf template
Code Block
languagejava
play.filters.enabled += play.filters.hosts.AllowedHostsFilter
play.filters.hosts {
  # You can use the "." pattern to match all hosts (not recommended in production).
  # Note that the filter also strips the dot character from the end of the host, so the example.com pattern will match example.com.
  # Uncomment to allow requests to intercax.com, its subdomains, and localhost:9000.
  # allowed = [".intercax.com", "localhost:9000"]
  allowed = ["."]
}

# CORSSecurity has to be enabled because modern browsers use it in fetch() calls and in user-agent "click" requests
# then allowedOrigins has to be null because browsers set Origin to null during Cross-Origin redirections

play.filters.enabled += play.filters.cors.CORSFilter
play.filters.cors {
  pathPrefixes = ["/authenticate/SAML2"]
  allowedOrigins = null
  allowedHttpMethods = ["GET", "POST", "PUT", "OPTIONS"]
  allowedHttpHeaders = ["Accept", "Authorization", "Content-Type"]
  preflightMaxAge = 3 days
}

# Security Filter ConfigurationFilter Configuration - Content Security Policy
play.filters.headers {
  contentSecurityPolicy = "default-src 'self';"
  contentSecurityPolicy = ${play.filters.headers.contentSecurityPolicy}" connect-src 'self' https://OURIDP.COM:IDPPORT;"
  contentSecurityPolicy = ${play.filters.headers.contentSecurityPolicy}" img-src 'self';"
  contentSecurityPolicy = ${play.filters.headers.contentSecurityPolicy}" style-src 'self' 'unsafe-inline';"
  contentSecurityPolicy = ${play.filters.headers.contentSecurityPolicy}" font-src 'self' 'unsafe-inline';"
  contentSecurityPolicy = ${play.filters.headers.contentSecurityPolicy}" script-src 'self' 'unsafe-inline' 'unsafe-eval';"
}

# the /authenticate/SAML2 route needs this to be able to pass crucial Headers back
# to the frontend
play.filters.headers.allowActionSpecificHeaders = true

...