0
votes

I am trying to configure my WSO2 Identity Server to set up service providers via a .xml file. Here are the steps I am taking:

  1. Paste the service provider .xml file into the $WSO2_HOME/repository/conf/identity/service-providers folder
  2. Run the wso2server.sh script in a fresh WSO2 environment (never setup, databases with empty tables)

The .xml file I created in step 1 was created using the "export" feature from the console, so I am pretty confident it is set up correctly. Just in case, this is the code (lines with "REMOVED" were removed for privacy):

<?xml version="1.0" encoding="UTF-8"?><ServiceProvider>
  <ApplicationName>__REMOVED__</ApplicationName>
  <Description>__REMOVED__</Description>
  <InboundAuthenticationConfig>
    <InboundAuthenticationRequestConfigs>
      <InboundAuthenticationRequestConfig>
        <InboundAuthKey>__REMOVED__</InboundAuthKey>
        <InboundAuthType>passivests</InboundAuthType>
        <InboundConfigType>standardAPP</InboundConfigType>
        <Properties/>
      </InboundAuthenticationRequestConfig>
      <InboundAuthenticationRequestConfig>
        <InboundAuthKey>__REMOVED__</InboundAuthKey>
        <InboundAuthType>openid</InboundAuthType>
        <InboundConfigType>standardAPP</InboundConfigType>
        <Properties/>
      </InboundAuthenticationRequestConfig>
      <InboundAuthenticationRequestConfig>
        <InboundAuthKey>__REMOVED__</InboundAuthKey>
        <InboundAuthType>oauth2</InboundAuthType>
        <InboundConfigType>standardAPP</InboundConfigType>
        <inboundConfiguration><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<oAuthAppDO>
    <oauthConsumerKey>__REMOVED__</oauthConsumerKey>
    <oauthConsumerSecret>__REMOVED__</oauthConsumerSecret>
    <applicationName>__REMOVED__</applicationName>
    <callbackUrl></callbackUrl>
    <oauthVersion>OAuth-2.0</oauthVersion>
    <grantTypes>client_credentials </grantTypes>
    <scopeValidators/>
    <pkceSupportPlain>true</pkceSupportPlain>
    <pkceMandatory>false</pkceMandatory>
    <userAccessTokenExpiryTime>3600</userAccessTokenExpiryTime>
    <applicationAccessTokenExpiryTime>3600</applicationAccessTokenExpiryTime>
    <refreshTokenExpiryTime>84600</refreshTokenExpiryTime>
    <idTokenExpiryTime>3600</idTokenExpiryTime>
    <audiences/>
    <bypassClientCredentials>false</bypassClientCredentials>
    <requestObjectSignatureValidationEnabled>false</requestObjectSignatureValidationEnabled>
    <idTokenEncryptionEnabled>false</idTokenEncryptionEnabled>
    <idTokenEncryptionAlgorithm>null</idTokenEncryptionAlgorithm>
    <idTokenEncryptionMethod>null</idTokenEncryptionMethod>
    <backChannelLogoutUrl></backChannelLogoutUrl>
    <tokenType>JWT</tokenType>
</oAuthAppDO>
]]></inboundConfiguration>
        <Properties/>
      </InboundAuthenticationRequestConfig>
    </InboundAuthenticationRequestConfigs>
  </InboundAuthenticationConfig>
  <LocalAndOutBoundAuthenticationConfig>
    <AuthenticationSteps/>
    <AuthenticationType>default</AuthenticationType>
    <alwaysSendBackAuthenticatedListOfIdPs>false</alwaysSendBackAuthenticatedListOfIdPs>
    <UseTenantDomainInUsername>false</UseTenantDomainInUsername>
    <UseUserstoreDomainInRoles>true</UseUserstoreDomainInRoles>
    <UseUserstoreDomainInUsername>false</UseUserstoreDomainInUsername>
    <EnableAuthorization>false</EnableAuthorization>
  </LocalAndOutBoundAuthenticationConfig>
  <RequestPathAuthenticatorConfigs/>
  <InboundProvisioningConfig>
    <ProvisioningUserStore/>
    <IsProvisioningEnabled>false</IsProvisioningEnabled>
    <IsDumbModeEnabled>false</IsDumbModeEnabled>
  </InboundProvisioningConfig>
  <OutboundProvisioningConfig>
    <ProvisioningIdentityProviders/>
  </OutboundProvisioningConfig>
  <ClaimConfig>
    <RoleClaimURI/>
    <LocalClaimDialect>false</LocalClaimDialect>
    <IdpClaim/>
    <ClaimMappings>
      <ClaimMapping>
        <LocalClaim>
          <ClaimUri>http://wso2.org/claims/role</ClaimUri>
          <claimId>0</claimId>
        </LocalClaim>
        <RemoteClaim>
          <ClaimUri>roles</ClaimUri>
          <claimId>0</claimId>
        </RemoteClaim>
        <RequestClaim>true</RequestClaim>
        <MandatoryClaim>false</MandatoryClaim>
      </ClaimMapping>
    </ClaimMappings>
    <AlwaysSendMappedLocalSubjectId>false</AlwaysSendMappedLocalSubjectId>
    <SPClaimDialects/>
  </ClaimConfig>
  <PermissionAndRoleConfig>
    <Permissions/>
    <RoleMappings/>
    <IdpRoles/>
  </PermissionAndRoleConfig>
  <IsSaaSApp>false</IsSaaSApp>
</ServiceProvider>

After the startup script completes, I don't see the service provider in the console:

enter image description here

Something strange I noticed - If I try to import the service provider manually using the console, I get an error on the UI reading:

Error in importing provided service provider [email protected] from file

My console output says:

Caused by: org.wso2.carbon.identity.application.common.IdentityApplicationManagementException: Application with the same name loaded from the file system.
        at org.wso2.carbon.identity.application.mgt.ApplicationManagementServiceImpl.doAddApplication(ApplicationManagementServiceImpl.java:1637)
        at org.wso2.carbon.identity.application.mgt.ApplicationManagementServiceImpl.createApplicationWithTemplate(ApplicationManagementServiceImpl.java:169)
        at org.wso2.carbon.identity.application.mgt.ApplicationManagementServiceImpl.importSPApplicationFromObject(ApplicationManagementServiceImpl.java:1025)
        ... 80 more

I found the source code this error is from and it is the ApplicationManagementServiceImpl.java file

if (ApplicationManagementServiceComponent.getFileBasedSPs().containsKey(applicationName)) {
    throw new IdentityApplicationManagementException(
            "Application with the same name loaded from the file system.");
}

which makes a call to ApplicationManagementServiceComponent.java.

private void buildFileBasedSPList() {
        String spConfigDirPath = CarbonUtils.getCarbonConfigDirPath() + File.separator + "identity"
                + File.separator + "service-providers";
        FileInputStream fileInputStream = null;
        File spConfigDir = new File(spConfigDirPath);
        OMElement documentElement;

        if (spConfigDir.exists()) {

            for (final File fileEntry : spConfigDir.listFiles()) {
                try {
                    if (!fileEntry.isDirectory()) {
                        fileInputStream = new FileInputStream(new File(fileEntry.getAbsolutePath()));
                        documentElement = new StAXOMBuilder(fileInputStream).getDocumentElement();
                        ServiceProvider sp = ServiceProvider.build(documentElement);
                        if (sp != null) {
                            fileBasedSPs.put(sp.getApplicationName(), sp);
                        }
                    }
                } catch (Exception e) {
                    log.error("Error while loading idp from file system.", e);
                } finally {
                    if (fileInputStream != null) {
                        try {
                            fileInputStream.close();
                        } catch (IOException e) {
                            log.error("Error occurred while closing file input stream for file " + spConfigDirPath, e);
                        }
                    }

The error is thrown because my service provider directory has a file with the same service provider name that is trying to be imported through the console. However, the service provider in my file system wasn't imported in the first place.

So my failure to import the service provider when the server gets configured prevents me from importing the files through the console later.

Any help is appreciated.

2

2 Answers

1
votes

The service providers deployed as the file $WSO2_HOME/repository/conf/identity/service-providers folder will not be visible in the UI. But it will be active in the system. Currently the InboundAuthenticationConfig in the deployed file is not supported. But, you can have the SAML configurations in the $WSO2_HOME/repository/conf/identity/sso-idp-config.xml file.

<SSOIdentityProviderConfig>
  <ServiceProviders>
    .......
    .......
    <ServiceProvider>
       <Issuer>_InboundAuthKey_</Issuer>
       <AssertionConsumerServiceURLs>
           <AssertionConsumerServiceURL>_url_</AssertionConsumerServiceURL>
       </AssertionConsumerServiceURLs>
      ......
       ......
   </ServiceProvider>
  </ServiceProviders>
</SSOIdentityProviderConfig>

Here the InboundAuthKey is the value of for saml InboundAuthenticationRequestConfig

0
votes

I've failed to setup service provider by storing file to $WSO2_HOME/repository/conf/identity/service-providers. OAuth2/token request always fails with error that the particular client_id is not found.

What works for me is to create python script to load XML using SOAP interface.

import zeep
from requests import Session
import os

session = Session()
#uncomment in case you use HTTPS without valid certificates
session.verify = False
transport = zeep.Transport(session=session)


def get_client(service):
    base_url = 'https://{IS_SERVICE_NAME}:{IS_PORT}/services/{SERVICE}?wsdl'.format(
        IS_SERVICE_NAME=os.environ["IS_SERVICE_NAME"],
        IS_PORT=os.environ["IS_PORT"],
        SERVICE=service)
    print("Getting client %s" % base_url)
    return zeep.Client(base_url, transport=transport)


def init_session():
    client = get_client('AuthenticationAdmin')

    client.service.login(username=os.environ["IS_USERNAME"],
                         password=os.environ["IS_PASSWORD"],
                         remoteAddress=os.environ["IS_SERVICE_NAME"])


def import_config(path):
    print("Calling IdentityApplicationManagementService")
    client_iam = get_client('IdentityApplicationManagementService')

    with open(path) as f:
        contents = f.read()

    # list of available namespaces
    # print client_iam.client_iam.namespaces
    sp_file_content_type = client_iam.get_type('ns2:SpFileContent')
    sp_file_content = sp_file_content_type(content=contents,
                                           fileName='service-provider.xml')
    client_iam.service.importApplication(sp_file_content)


if __name__ == '__main__':
    assert "IS_USERNAME" in os.environ, "Define IS_USERNAME env variable"
    assert "IS_PASSWORD" in os.environ, "Define IS_PASSWORD env variable"
    assert "IS_SERVICE_NAME" in os.environ, "Define IS_SERVICE_NAME env variable"
    assert "IS_PORT" in os.environ, "Define IS_PORT env variable"

    init_session()
    import_config('/conf/service-provider.xml')

This SOAP interface is enabled by setting in carbon.xml.

<HideAdminServiceWSDLs>false</HideAdminServiceWSDLs>