Configuring SAML Single Sign On

Use WLST to enable SAML Single Sign On (SSO) on WebLogic Server domains.

When you enable SAML SSO on a WebLogic domain, you need to configure security or authentication providers, SAML 2.0 general services, and, depending on the role of the domain, either Identity Provider services or Service Provider services. For more information on the general process for configuring SAML SSO in WebLogic, see Configuring SAML 2.0 Services in Administering Security for Oracle WebLogic Server.

Import Partner Properties

Before you use WLST offline to configure SAML SSO, you need to export your federated partners' metadata files, create either an Identity Provider partner properties file or a Service Provider partner properties file, and place both files in the DOMAIN_HOME/security directory.

  1. Use WLST online to export metadata files from your federated partners. WLST offline does not support exporting metadata.

  2. Create a partner properties file :

    • If using WebLogic Server as an Identity Provider, then create a file and name it saml2sppartner.properties. Use the following example as a reference. Any properties preceded by # are optional.

      saml2.sp.partners=401kPartner,hmoPartner
      401kPartner.metadata.file=401ksp_metadata.xml 
       
      hmoPartner.metadata.file=hmosp_metadata.xml
      # hmoPartner.enabled=true
      # hmoPartner.description=
      # hmoPartner.mapperClassName=
      # hmoPartner.wantAssertionsSigned=false
      # hmoPartner.timeToLive=100
      # hmoPartner.timeToLiveOffset=50
      # hmoPartner.generateAttributes=false
      # hmoPartner.keyInfoIncluded=false
      # hmoPartner.includeOneTimeUseCondition=false
    • If using WebLogic Server as a Service Provider, then create a file and name it saml2idppartner.properties. Use the following example as a reference. Any properties preceded by # are optional.

      saml2.idp.partners=company1Partner,company2Partner
      company1Partner.description=Company1 IDP Partner
      company1Partner.metadata.file=company1idp_metadata.xml
      company1Partner.enabled=true
      company1Partner.redirectUris=/company1app/target.jsp,/company1app/index.jsp 
       
      company2Partner.metadata.file=company2idp_metadata.xml
      company2Partner.redirectUris=/company2app/target.jsp,/company2app/welcome.jsp
      company2Partner.issuerUri=
      company2Partner.enabled=true
      company2Partner.virtualUserEnabled=true
      # company2Partner.mapperClassName=
      # company2Partner.wantAssertionsSigned=false
      # company2Partner.processAttributes=false

    To use a custom name mapper, uncomment the appropriate mapperClassName property and set it to the fully qualified name of your implementation class. An Identity Provider partner mapper must implement com.bea.security.saml2.providers.SAML2IdentityAsserterNameMapper; do not use the interface name as the property value.

  3. Save the partner metadata file(s) and the partner properties file in the DOMAIN_HOME/security directory.

The Administration Server imports these partner definitions during security-provider initialization. Placing the files while the domain is offline does not itself import the partners; start or restart the Administration Server after completing the offline configuration.

Sample: Configure WebLogic Server as an Identity Provider Site with SAML SSO

Use this sample WLST script as a starting point to create your own script that configures SAML 2.0 Single Sign On (SSO) on a WebLogic Server instance working as an Identity Provider.

Note:

If you use WLST offline to configure SAML SSO, then you need to create a Service Provider partner properties file. This properties file specifies important SAML 2.0 partner metadata that is required by your federated partners. For more information on partner properties files, see Import Partner Properties.

Example C-1 Configure WebLogic Server as an Identity Provider site and enable SAML SSO

Update placeholder text with real values. Placeholder text is enclosed by @ symbols. For example, @admin_username@.

The offline set calls below accept clear-text passphrases; WLST encrypts these fields when writing the domain. Replace all sample aliases and passphrases with the values for your key stores, in addition to replacing the placeholders enclosed in @ symbols.

import os
import sys

def getEnvVar(var):
  val=os.environ.get(var)
  if val==None:
    print "ERROR: Env var ",var, " not set."
    sys.exit(1)
  return val

# Configure SAML2 Credential Mappers
def configSAML2CM():
 cd('/SecurityConfiguration/@domainName@/Realms/@realmName@')
 create('@saml2CMName@', 'com.bea.security.saml2.providers.SAML2CredentialMapper', 'CredentialMapper')
 cd('CredentialMappers')
 cd('@saml2CMName@')
 cmo.setIssuerURI('@url@/company1idp_entityid')

# Configure SAML2 SSO Service
def configSSOService(AdminServerName):
    cd('/Servers/' + AdminServerName)
    create(AdminServerName, 'SingleSignOnServices')
    cd('SingleSignOnServices/' + AdminServerName)
    cmo.setContactPersonGivenName('company1ContactPersonGivenName')
    cmo.setContactPersonSurName('company1ContactPersonSurName')
    cmo.setContactPersonType('technical')
    cmo.setContactPersonCompany('company1ContactPersonCompany')
    cmo.setContactPersonTelephoneNumber('company1ContactPersonTelephoneNumber')
    cmo.setContactPersonEmailAddress('company1ContactPersonEmailAddress')
    cmo.setOrganizationName('company1OrganizationName')
    cmo.setOrganizationURL('company1OrganizationURL')
    cmo.setEntityID('@url@/company1idp_entityid')
    cmo.setPublishedSiteURL('@url@/saml2')
    cmo.setLoginURL('@url@/loginapp/loginapp.jsp')
    cmo.setIdentityProviderPOSTBindingEnabled(True)
    cmo.setIdentityProviderArtifactBindingEnabled(True)
    cmo.setIdentityProviderRedirectBindingEnabled(True)
    cmo.setIdentityProviderPreferredBinding('HTTP/POST')
    cmo.setSSOSigningKeyAlias('company1IdPSSOSigningKeyAlias')
    set('SSOSigningKeyPassPhraseEncrypted',
        'company1IdPSSOSigningKeyPassPhrase')
    if '@twoWaySSLEnabled@' == 'true':
        cmo.setTransportLayerSecurityKeyAlias('company1IdPTLSKeyAlias')
        set('TransportLayerSecurityKeyPassPhraseEncrypted',
            'company1IdPTLSKeyPassPhrase')
    cmo.setIdentityProviderEnabled(True)


def configSSL(AdminServerName):
    cd('/Servers/' + AdminServerName)
    cmo.setKeyStores('CustomIdentityAndCustomTrust')
    cmo.setCustomTrustKeyStoreFileName('@certsDir@/company1IdPTrust.jks')
    set('CustomTrustKeyStorePassPhraseEncrypted',
        'company1IdPTrustKeyStorePassPhrase')
    cmo.setCustomIdentityKeyStoreFileName('@certsDir@/company1IdPIdentity.jks')
    set('CustomIdentityKeyStorePassPhraseEncrypted',
        'company1IdPIdentityKeyStorePassPhrase')
    create(AdminServerName, 'SSL')
    cd('SSL/' + AdminServerName)
    cmo.setEnabled(True)
    cmo.setListenPort(int('@sport@'))
    cmo.setTwoWaySSLEnabled('@twoWaySSLEnabled@' == 'true')
    cmo.setClientCertificateEnforced(
        '@clientCertificateEnforced@' == 'true')
    cmo.setHostnameVerificationIgnored(False)
    cmo.setServerPrivateKeyAlias('company1IdPServerKeyAlias')
    set('ServerPrivateKeyPassPhraseEncrypted',
        'company1IdPServerKeyPassPhrase')

# Optional: Create cluster

# Create IDP domain

readDomain('@domainPath@')
configSAML2CM()
configSSOService('@adminServerName@')
configSSL('@adminServerName@')
updateDomain()
closeDomain()
print 'Domain Updated with Identity Provider configured'

exit()

Sample: Configure WebLogic Server as a Service Provider Site with SAML SSO

Use this sample WLST script as a starting point to create your own script that configures SAML 2.0 Single Sign On (SSO) on a WebLogic Server instance working as a Service Provider.

Note:

If you use WLST offline to configure SAML SSO, then you need to create an Identity Provider partner properties file. This properties file specifies important SAML 2.0 partner metadata that is required by your federated partners. For more information on partner properties files, see Import Partner Properties.

Example C-2 Configure WebLogic Server as a Service Provider site and enable SAML SSO

Update placeholder text with real values. Placeholder text is enclosed by @ symbols. For example, @admin_username@.

The offline set calls below accept clear-text passphrases; WLST encrypts these fields when writing the domain. Replace all sample aliases and passphrases with the values for your key stores, in addition to replacing the placeholders enclosed in @ symbols.

import os
import sys

def getEnvVar(var):
  val=os.environ.get(var)
  if val==None:
    print "ERROR: Env var ",var, " not set."
    sys.exit(1)
  return val

# Create domain
def createDomain(domainName, adminServerName):
  readTemplate('@templateJar@')
  set('Name', domainName)
  setOption('DomainName', domainName)
  cd('/Servers/AdminServer')
  set('ListenPort', int('@admin_port@'))
  set('Name', adminServerName)
  cd('/Security/' + domainName + '/User/weblogic')
  cmo.setName('@admin_username@')
  cmo.setPassword('@admin_password@')
  setOption('OverwriteDomain', 'true')
  writeDomain('@domainPath@')
  closeTemplate()
  print 'Domain Created'

# Create a cluster
def createCluster(clusterName):
  cd('/')
  cl=create(clusterName, 'Cluster')
  cluster_type='@cluster_type@'
  number_of_ms=int('@number_of_ms@')
  managed_server_name_base='@managed_server_name_base@'
  managed_server_name_base_svc='@managed_server_name_base_svc@'

  if cluster_type == "CONFIGURED":
    for index in range(0, number_of_ms):
      cd('/')
      msIndex = index+1
      name = managed_server_name_base + str(msIndex)
      name_svc = managed_server_name_base_svc + str(msIndex)
      create(name, 'Server')
      cd('/Servers/' + name + '/')
      print('managed server name is ' + name)
      set('ListenPort', int('@server_port@'))
      set('NumOfRetriesBeforeMSIMode', 0)
      set('RetryIntervalBeforeMSIMode', 1)
      set('Cluster', clusterName)

  else:
    print('Configuring Dynamic Cluster ' +  clusterName)
    templateName = '@cluster_name@-template'
    print('Creating Server Template: ' + templateName)
    st1=create(templateName, 'ServerTemplate')
    print('Done creating Server Template: ' + templateName)
    cd('/ServerTemplates/' + templateName)
    cmo.setListenPort(int('@server_port@'))
    cmo.setCluster(cl)
    print('Done setting attributes for Server Template: ' + templateName);
    cd('/Clusters/' + clusterName)
    create(clusterName, 'DynamicServers')
    cd('DynamicServers/' + clusterName)
    set('ServerTemplate', st1)
    set('ServerNamePrefix', managed_server_name_base)
    set('DynamicClusterSize', number_of_ms)
    set('MaxDynamicClusterSize', number_of_ms)
    set('CalculatedListenPorts', false)

  print('Done setting attributes for Dynamic Cluster: ' + clusterName);

# Configure SAML Authentication Provider
def configSAMLAtn():
  cd('/SecurityConfiguration/@domainName@/Realms/@realmName@')
  samlatn = create('@samlAtnName@', 'weblogic.security.providers.saml.SAMLAuthenticator', 'AuthenticationProvider')
  samlatn.setControlFlag('SUFFICIENT')

# Configure SAML2 Identity Asserter
def configSAML2IA():
  cd('/SecurityConfiguration/@domainName@/Realms/@realmName@')
  create('@saml2IAName@', 'com.bea.security.saml2.providers.SAML2IdentityAsserter', 'AuthenticationProvider')
  cd('AuthenticationProvider')
  cd('@saml2IAName@')
  # cmo.setReplicatedCacheEnabled(Boolean('@replicatedCacheEnabled@'))

def reConfigDefaultAtn():
  cd('/SecurityConfiguration/@domainName@/Realms/@realmName@')
  delete('DefaultAuthenticator', 'AuthenticationProvider')
  delete('DefaultIdentityAsserter','AuthenticationProvider')
  defaultAtn=create('DefaultAuthenticator', 'weblogic.security.providers.authentication.DefaultAuthenticator', 'AuthenticationProvider')
  defaultAtn.setControlFlag('REQUIRED')
  create('DefaultIdentityAsserter', 'weblogic.security.providers.authentication.DefaultIdentityAsserter', 'AuthenticationProvider')

# Configure SAML2 SSO Service
def configSSOService(AdminServerName):
    cd('/Servers/' + AdminServerName)
    create(AdminServerName, 'SingleSignOnServices')
    cd('SingleSignOnServices/' + AdminServerName)
    cmo.setContactPersonGivenName('401kContactPersonGivenName')
    cmo.setContactPersonSurName('401kContactPersonSurName')
    cmo.setContactPersonType('technical')
    cmo.setContactPersonCompany('401kContactPersonCompany')
    cmo.setContactPersonTelephoneNumber('401kContactPersonTelephoneNumber')
    cmo.setContactPersonEmailAddress('401kContactPersonEmailAddress')
    cmo.setOrganizationName('401kOrganizationName')
    cmo.setOrganizationURL('401kOrganizationURL')
    cmo.setEntityID('@url@/401ksp_entityid')
    cmo.setPublishedSiteURL('@url@/saml2')
    cmo.setServiceProviderPOSTBindingEnabled(True)
    cmo.setServiceProviderArtifactBindingEnabled(True)
    cmo.setServiceProviderPreferredBinding('HTTP/POST')
    cmo.setSSOSigningKeyAlias('401kSPSSOSigningKeyAlias')
    set('SSOSigningKeyPassPhraseEncrypted',
        '401kSPSSOSigningKeyPassPhrase')
    if '@twoWaySSLEnabled@' == 'true':
        cmo.setTransportLayerSecurityKeyAlias('401kSPTLSKeyAlias')
        set('TransportLayerSecurityKeyPassPhraseEncrypted',
            '401kSPTLSKeyPassPhrase')
    cmo.setServiceProviderEnabled(True)


def configSSL(AdminServerName):
    cd('/Servers/' + AdminServerName)
    cmo.setKeyStores('CustomIdentityAndCustomTrust')
    cmo.setCustomTrustKeyStoreFileName('@certsDir@/401kSPTrust.jks')
    set('CustomTrustKeyStorePassPhraseEncrypted',
        '401kSPTrustKeyStorePassPhrase')
    cmo.setCustomIdentityKeyStoreFileName('@certsDir@/401kSPIdentity.jks')
    set('CustomIdentityKeyStorePassPhraseEncrypted',
        '401kSPIdentityKeyStorePassPhrase')
    create(AdminServerName, 'SSL')
    cd('SSL/' + AdminServerName)
    cmo.setEnabled(True)
    cmo.setListenPort(int('@sport@'))
    cmo.setTwoWaySSLEnabled('@twoWaySSLEnabled@' == 'true')
    cmo.setClientCertificateEnforced(
        '@clientCertificateEnforced@' == 'true')
    cmo.setHostnameVerificationIgnored(False)
    cmo.setServerPrivateKeyAlias('401kSPServerKeyAlias')
    set('ServerPrivateKeyPassPhraseEncrypted',
        '401kSPServerKeyPassPhrase')

# Open the existing domain and configure SP
createDomainRequested = '@createDomain@'
createClusterRequested = '@createCluster@'

if createDomainRequested == 'true':
    createDomain('@domainName@', '@adminServerName@')

readDomain('@domainPath@')
if createClusterRequested == 'true':
    createCluster('@clusterName@')

configSAMLAtn()
configSAML2IA()
reConfigDefaultAtn()
configSSOService('@adminServerName@')
configSSL('@adminServerName@')

updateDomain()
closeDomain()
print 'Domain Updated with Service Provider Configured'

exit()